import javax.microedition.io.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
import java.io.*;
import java.util.*;


//#if Nokia
import com.nokia.mid.ui.*;
public class Main extends com.nokia.mid.ui.FullCanvas implements Runnable, RecordFilter, RecordComparator

//#elif Siemens && (!SX1)
import com.siemens.mp.color_game.*;
import com.siemens.mp.game.*;
public class Main extends com.siemens.mp.color_game.GameCanvas implements Runnable, RecordFilter, RecordComparator

//#else
public class Main extends Canvas implements Runnable, RecordFilter, RecordComparator
//#endif
{
	static boolean isBannerLoaded;
	static String banner;
	static int bannerImageIndex = 32;

	static int snow[] = null;

	static int sin[] = null;
	static int cos[] = null;

    static int anims[][] = null;

    static String text[] = null;
	
	static final int GHOST_DATA_SIZE 				= 2000; // bytes

	static final int NO_ACTION 						= -15;

	static final int STATE_BIATHLON_RUN				= 0;
	static final int STATE_BIATHLON_RUN_FINISH		= 1;
	static final int STATE_BIATHLON_RUN_SCORES		= 2;
	static final int STATE_BIATHLON_SHOOT			= 3;
	static final int STATE_BIATHLON_SHOOT_FINISH	= 4;

	static final int STATE_SKATER_RUN 				= 10;
	static final int STATE_SKATER_RUN_FINISH		= 11;
	static final int STATE_SKATER_RUN_SCORES		= 12;

	static final int STATE_SKIJUMP_RUN 				= 20;
	static final int STATE_SKIJUMP_RUN_FINISH		= 21;
	static final int STATE_SKIJUMP_RUN_SCORES		= 22;

	
	static final int STATE_PLACE 					= 50;

	static final int STATE_MENU						= 70;

	static final int STATE_EDITOR					= 80;
	static final int STATE_EDITOR_FINISH			= 81;


	static final int STATE_INTRO					= 90;
	static final int STATE_LOGO						= 91;

	static int[][] abcw = 
	 	 {
//#if Size_0	
//	                       0 1 2 3 4 5 6 7 8 9   a b c d e f g h i j k l m n o p q r s t u v w x y z  # . : _ , * @ ( )	
		{6,4,6,6,6,6,6,6,6,6,  6,6,6,6,6,6,6,6,3,6,6,6,7,6,6,6,6,6,6,7,6,6,7,7,7,5, 5,2,2,6,2,9,9,4,4,
		 4, 6,6,6,6,6, 8, 6, 6,6,6,6, 3,3,3,3, 6, 6,6,6,6, 6,6,6,6, 5,5, 6,7},
//#else
		{8,5,8,8,7,8,8,7,8,8,  8,7,8,8,7,7,8,8,4,8,8,7,10,8,8,7,8,8,7,8,8,8,10,8,8,7, 7,4,4,6,4,9,9,4,4,
		 4, 8,8,8,8,8, 9, 8, 7,7,7,7, 4,4,4,4, 8, 8,8,8,8, 8,8,8,8, 7,7, 6,7},
//#endif

		 {6,6,6,6,6,6,6,6,6,6,3},
		 {6,4,5,5,5,5,5,5,5,5,5,5,4,5,5,5}};
	static int[][] abcx = null;
	static int[][] abcy = null;
	static int[] abch = {9,11,8};
	static int abci = 0;

	static byte ghost_data[] = null;
	static int ghost_data_ptr = 0;
	static int ghost_data_count = 0;

	static byte ghost_data_w[] = null;
	static int ghost_data_ptr_w = 0;
	static int ghost_data_count_w = 0;

	static int rounds_count = 3;
	static int rounds_passed = 0;

    static WinterSports midlet;
    Thread mainThread;

    static Image img[] = null;

    static String img_names[] = null;

//#if GX10
	static Image img_cache[] = null;
//#endif

    static int logo0_index = -1;
    static int logo1_index = -1;
    static int abc_index[] = {-1,-1,-1};
    static int rast_index = -1;
    static int snowflake_index = -1;

    static Frame fT[] = null;
    static Frame fSn[] = null;
    static Frame fTree[] = null;
    static Frame fFlag[] = null;
    static Frame fBg = null;

    static Frame fChess = null;
    static Frame fTarget = null;
    static Frame fMeter = null;
    static Frame fMeterred = null;
    static Frame fHeart = null;
    static Frame fAmmo = null;

    static Frame fSnow = null;
    static Frame fSign = null;

    static Frame fBoard = null;
    static Frame fGo[] = null;

    static Dynamic man = null;
    static Dynamic ghost = null;

    static Hashtable hp = null;
    static Vector v = null,v1 = null,v2 = null;


    static int s_w;					// physical screen size
    static int s_h;

  	static Random rand;

  	static int state;
	static boolean initOK = false;
    static int action = NO_ACTION, key_action = NO_ACTION, g_action, game_action;
	static boolean running = false;

	// 
	static int[] track_x = null; 		// array or track points
	static int[] track_y = null;

	static int track_width = 0;
	static int track_width_one = 0;

    static int a_x_d = 0;				// displacement 
    static int a_y_d = 0;               

    static int a_x_range = 0;			// displacement range

	static int i,i2,j,k,x,y,x1,y1,x2,y2,w,h,w1,h1,w2,h2,n,dx,dy,idx,itotal,tracks_total;
	static int rel_dx,rel_dy;
	static int x_bound, y_bound_top, y_bound_bottom, y_bg_top;
	static int start_x, start_y;

	static int track_x_sum, shoot_bound, points, total_points;

	static int distance = 0;

	static String str, str2, str3, message = null;
	static char buf[] = null;

	static int bgTop = 0;

    static Vector vMenu;
    static Vector vMenuId;
    static Vector vState;
    static int menuIndex = 0;
    static String menuName;
	static int menuDisp,menuRange,menuHeight,menuTop,logoTop;
    static boolean isPointer = true;
    static boolean isState = true;
    static int menuLast = -1;
    static boolean showLogo = false; 
    static Vector vMenuName;
    static int menuWidth;
    static int menuItemWidth;
    static int menuSize;

    static char editText[] = null;
    static String letters = " 0123456789abcdefghijklmnopqrstuvwxyz.,:*@_#";
    static String numbers = " +0123456789_#";
    static int editX, editY, ew;
    static char ch;

	// tasks
    static int taskTimes[] = null;
    static int tasks[] = null;
    static int task_i = 0;
    static boolean needRepaint = false;

	static InputStream in = null;

    Font font = null;

    static int si,sl,sx,sn;
    static char sc;
    static int tabx[] = new int[2];
    static int tabi = 0;
    static int tabw = 0;

    Thread t = null;
    static long tstart = 0, tcur = 0;
    static boolean runFlag = true;

//    static int model = 4;

    static boolean resourcesLoaded = false;

    static String str_yes, str_no;

	static Dynamic dyn = new Dynamic();

//#if MIDP2
	protected void sizeChanged(int w,int h)
	{
		s_w = w;
		s_h = h;
	}
//#endif
                                                                                
	public Main(WinterSports midlet)
	{

//#if Siemens && (!SX1)
		super(false); // for game canvas
//#endif

    	try
    	{
	    	this.midlet = midlet;
//#if MIDP2
			setFullScreenMode(true);
//#endif
			s_w = getWidth();
			s_h = getHeight();

			ew = 10;
			w = 104;


//#if Size_0
			ew = 8;
			w = 81;
//#endif

			abcx = new int[abcw.length][];
			abcy = new int[abcw.length][];
			for (j = 0; j < abcw.length; j++)
			{
				x = 0;
				y = 0;
				abcx[j] = new int[abcw[j].length];
				abcy[j] = new int[abcw[j].length];
				for (int i = 0; i < abcw[j].length; i++)
				{
					abcx[j][i] = x;
					abcy[j][i] = y;
					x += abcw[j][i];
					if (x > w)
					{
						x = 0;
						y += 9;
					}
				}
			}

   			buf = new char[30]; // char buffer
    		isNameSaved = false;

	    	try
    		{
				rs = RecordStore.openRecordStore("wsports",false);
		        if (getVar(C_UNAME) > 0)
		        {
		        	uname = r_player;
	    	    	isNameSaved = true;
		        }	
			}
			catch(Exception ex)
			{
		    	try
    			{
					rs = RecordStore.openRecordStore("wsports",true);
					for (i = 0; i < 9; i++)
					{
						player = gp("n" + i);
						putRecord(C_ADD_RECORD,G_BIATHLON,Integer.parseInt(gp("s0_" + i)));
						putRecord(C_ADD_RECORD,G_SKATER,  Integer.parseInt(gp("s1_" + i)));
						putRecord(C_ADD_RECORD,G_SKIJUMP, Integer.parseInt(gp("s2_" + i)));
					}
				}
				catch(Exception ex2){}
			}
			version = midlet.getAppProperty("MIDlet-Version");
		
           	rand = new Random(System.currentTimeMillis());
			img = new Image[71];

			img_names = new String[img.length];
			for (i = 0; i < img.length; i++)
			{
				img[i] = null;
				img_names[i] = null;
			}
			abc_index[0] = img.length - 1;
			abc_index[1] = abc_index[0] - 1;
			abc_index[2] = abc_index[1] - 1;

			logo0_index = abc_index[2] - 1;
			logo1_index = logo0_index - 1;
			rast_index = logo1_index - 1;
			snowflake_index = rast_index - 1;

		   	editText = new char[5];

			state = STATE_INTRO;
			logoTop = -1;

			state_delay = 40;
			isKeyPressed = false;
			action = NO_ACTION;

			createImage(snowflake_index, "/Res/sf.png");
			createImage(logo0_index, "/Res/xi.png");
			if (img[logo0_index] != null)
			{
				w1 = getImageWidth(logo0_index);
				h1 = getImageHeight(logo0_index);
				fBg = new Frame(logo0_index,0,0,w1,h1,w1,h1);
			}
//#if GX10
			img_cache = new Image[3];
			img_cache[0] = Image.createImage("/Res/xl.png");
			img_cache[1] = Image.createImage("/Res/xt.png");
			img_cache[2] = Image.createImage("/Res/rast.png");
//#endif

			text = new String[70];
			loadText();

			str_yes = text[13];
			str_no = text[14];

			while (str_yes.length() > str_no.length()) str_no = " " + str_no;
			while (str_yes.length() < str_no.length()) str_yes = " " + str_yes;

			snow = new int[8];
	    	for (i = 0; i < snow.length; i++)
	    	{
				x = rnd(s_w);
				y = rnd(s_h);
				k = rnd(1);
				h = rnd(10) * 2 + 10;
			   	snow[i] =  (x << 24) & 0xFF000000;
			   	snow[i] |= (y << 16) & 0x00FF0000;
	    		snow[i] |= (k << 8)  & 0x0000FF00;
			   	snow[i] |= h & 0x000000FF;
			}

			isBannerLoaded = true;
			banner = midlet.getAppProperty("banner");
			if (banner != null) isBannerLoaded = false;
			else bannerImageIndex = -1;


			Display.getDisplay(midlet).setCurrent(this); 

       		initTasks();

			start();
		}
		catch(Exception ex)
		{
//			ex.printStackTrace();
		}
    }

    static void loadText()
    {
    	DataInputStream din = null;
		try
		{
			din = new DataInputStream(midlet.getClass().getResourceAsStream("/Res/en"));
			for(j = 0; j < text.length; j++) text[j] = din.readUTF();
		}
		catch(Exception e){}

		try
		{
			din.close();
		}
		catch(Exception ex){}
		din = null;
    }

    static int initTasks()
    {
		taskTimes = new int[1];
		taskTimes[0] = 75;
		tasks = new int[taskTimes.length];
		tasks[0] = 0;
		tstart = tcur = System.currentTimeMillis();
		runFlag = false;
		running = true;
		return 0;
    }

    static int rnd(int interval)
    {
    	return (rand.nextInt() & 0x07FFFFFFF) % interval;
    }

    int isScreen = 0;

    void setScreen(String msg)
    {
    	message = msg;
    	isScreen = 1;
    	doRepaint();
    }

    static Frame gf(String name,int i1, int i2, int i3)
    {
    	StringBuffer sb = new StringBuffer();
    	sb.append(name);
    	sb.append(Integer.toString(i1));
    	sb.append('_');
    	sb.append(Integer.toString(i2));
    	sb.append('_');
    	sb.append(Integer.toString(i3));
    	return gf(sb.toString());
    }

    static int gf_count = 0;
    static Frame gf(String name)
    {
    	try
    	{
	    	String str = gp(name);
   		 	if (str != null)
	   	 	{
		    	Vector v = parse(str);
		    	int h = ((Integer)v.elementAt(0)).intValue();
  			    str = gp("i" + h);
  			    int w1,w2,h1,h2;

  			    if (str != null)
  			    {
  			    	if (img_names[h] == null)
  			    	{
  			    		img_names[h] = str;
  			    	}
			    	w1 = w2 = ((Integer)v.elementAt(3)).intValue();
		   		 	h1 = h2 = ((Integer)v.elementAt(4)).intValue();

		    		if (v.size() > 5) w2 = ((Integer)v.elementAt(5)).intValue();
			    	if (v.size() > 6) h2 = ((Integer)v.elementAt(6)).intValue();

		    		return new Frame(h,((Integer)v.elementAt(1)).intValue(),((Integer)v.elementAt(2)).intValue(),w1,h1,w2,h2);
				}
				if (++gf_count ==  8)
				{
					gf_count = 0;
					midlet.main.doRepaint();
				}
			}
		}
		catch(Exception ex){}
		return null;
    }

    boolean enqueue_abc(int index)
    {
    	if (img[abc_index[index]] == null)
    	{                 
    		img_names[abc_index[index]] = "abc" + index;
	    	return true;
		}
		return false;
    }

    boolean loadLogo()
    {
    	boolean res = false;
    	if (img[rast_index] == null)
    	{
			img_names[rast_index] = "rast";
			res = true;
		}
		if (img[logo0_index] == null) 
		{
			img_names[logo0_index] = "xl";
			res = true;
		}
		if (img[logo1_index] == null) 
		{
			img_names[logo1_index] = "xt";
			res = true;
		}
		return res;
    }

    void release()
    {
    	initOK = paused = false;

   		fT = null;
   		fSn = null;
   		fTree = null;
   		fFlag = null;

   		fT = null;
		fSnow = null;

		fBg = null;
		fChess = null;
		fTarget = null;
		fMeter = null;
		fMeterred= null;
		fHeart = null;
		fAmmo = null;

		fBoard = null;
		fSign = null;

   		fSnow = null;
   		fGo = null;

   		track_x = null;

   		for (i = 0; i < img.length; i++)
   		if ((i != abc_index[0]) && (i != rast_index) && (i != snowflake_index))
   		{
   			img[i] = null;
   			img_names[i] = null;
		}

		anims = null;
		sin = null;
		cos = null;

    	vMenu = null;
    	vMenuId = null;
    	vState = null;
    	vMenuName = null;
   		man = null;
   		ghost = null;
   		hp = null;
   		v = v1 = v2 = null;
   		gd = null;
   		font = null;
   		str = str2 = null;

      	state = STATE_MENU;
		resourcesLoaded = false;
		System.gc();
    }

    void initEditor(String name,String value,int count) 
    {
    	menuName = name;

    	editText = new char[count];
    	for (i = 0; i < count; editText[i] = value.charAt(i++));

    	state = STATE_EDITOR;
    	if (enqueue_abc(0)) loadImages(false);
    	go_delay = 0;
    	editX = editY = idx = 0;
    	initOK = true;
    }

    void initMenu(String name, boolean isPointer, boolean isState, boolean showLogo) 
    {
    	initOK = false;
    	state = STATE_MENU;
		menuIndex = menuDisp = 0;
		vMenuName = prepareText(name,s_w - 8);
		menuWidth = 0;

		menuSize = vMenuName.size();
		for (i = 0; i < menuSize; i++)
		{
			menuName = (String)vMenuName.elementAt(i);
			j = getStringWidth(menuName);
			if (j > menuWidth) menuWidth = j;
		}

		if (paused) menuTop = 6;
		else
		{
//#if Size_0
			if (menuLevel != 0) logoTop = 6;
//#endif
			menuTop = logoTop + (showLogo ? 0 : 16);
		}

		menuHeight = 16;
		menuRange = (s_h - menuTop + (menuHeight >> 1)) / menuHeight - menuSize + 1;
		this.isPointer = isPointer;
		this.showLogo = showLogo;
		this.isState = isState;
		vMenu = new Vector();
		vMenuId = new Vector();
		if (isState) vState = new Vector();
    	menuItemWidth = 0;
		for (tabi = 0; tabi < tabx.length; tabi++) tabx[tabi] = 0;
		needCalcTabulations = true;
		tabi = 0;
    	loadText();
    	if (enqueue_abc(0) || (paused || resourcesLoaded ? false : loadLogo())) loadImages(false);
    	go_delay = 0;
    	initOK = true;
    }


    void init(int game_id,boolean needGhost,String code, int post_mode)
    {
    	try
    	{
			i = 27;
			if (game_id == G_SKATER) i = 28;
			if (game_id == G_BIATHLON) i = 29;
			running = initOK = false;

			needLoadingIndicator = true;
			setScreen(text[i]); // loading
			text[42] = text[43] = text[44] = text[45] = text[46] = null;

			ghost_data_w = null;

			doRepaint();
			release();

			m_v1 = m_v2 = 0;
			fGo = new Frame[4];
       	   	for (i = 0; i < fGo.length; i++) fGo[i] = gf("go" + i);
       	   	fBoard = gf("board");
       	   	switch(game_id)
       	   	{
			case G_SKIJUMP:
				state = STATE_SKIJUMP_RUN;
				fTree = new Frame[1];
				fT = new Frame[4];
//#if Nokia
				fSn = new Frame[8];
//#else
				fSn = new Frame[16];
//#endif

				for (i = 0; i < fT.length; i++) fT[i] = gf("jt" + i);
				for (i = 0; i < fSn.length; i++) fSn[i] = gf("jm" + i);
				for (i = 0; i < fTree.length; i++) fTree[i] = gf("tree" + i);
				fSnow = gf("jsn");
				fBg = gf("bg0");
				fSign = gf("dsign");
				fMeter = gf("jw");
				fMeterred = gf("jwp");

				fChess = gf("mtr");
				fBoard = gf("mtrred");

				fTarget = gf("mw");


				track_x = new int[5];
				track_x[0] = 48 * 4;
				track_x[1] = 20;
				track_x[2] = 20;
				track_x[3] = 576;
				track_x[4] = 400;

				track_width = 0;
				for (i = 0; i < track_x.length; i++) track_width += track_x[i];

				y_bg_top = ((s_h - fBg.fh) >> 1) + (track_width >> 5);

				y_bound_top = s_h / 4;

				y_bound_bottom = s_h * 2 / 3;

				x_bound = s_w / 3;

				start_y = y_bound_top;

				a_x_range = track_width - s_w;

				v1 = parse(gp("sin"));
				sin = new int[v1.size()];
    			for (j = 0; j < sin.length; j++) sin[j] = ((Integer)v1.elementAt(j)).intValue();
				v1 = parse(gp("cos"));
				cos = new int[v1.size()];
    			for (j = 0; j < cos.length; j++) cos[j] = ((Integer)v1.elementAt(j)).intValue();

				man = new Dynamic();
				man.init(0,0,null,false);
				if (needGhost)
				{
					ghost = new Dynamic();
					ghost.init(0,0,null,true);
				}

	           	enqueue_abc(2);
	           	break;
			case G_SKATER:
				state = STATE_SKATER_RUN;
				fTarget = gf("aud");
				fAmmo = gf("cones");
				fSnow = gf("snow");
				fBg = gf("bg1");
				fChess = gf("chess");
				fSign = gf("dsign");

				fT = new Frame[2];
				for (i = 0; i < fT.length; i++) fT[i] = gf("adv" + i);

				if (isBannerLoaded == true && banner != null)
				{
					img_names[fT[1].index] = banner;
				}

				readAnimation("a_s",4);

				man = new Dynamic();
				man.init(20,0,"s",false);
				if (needGhost)
				{
					ghost = new Dynamic();
					ghost.init(20,0,"sg",true);
				}

				track_width = 3200;
				tracks_total = track_width;

				a_x_range = track_width - s_w + 100;
				x_bound = s_w - (s_w >> 2);

	           	enqueue_abc(2);
	           	break;
			case G_BIATHLON:
				state = STATE_BIATHLON_RUN;
				track_x = new int[9];
				track_y = new int[track_x.length];

				track_x[0] = 512;
				track_x[1] = 384;
				track_x[2] = 256;
				track_x[3] = 256;
				track_x[4] = 384;
				track_x[5] = 128;
				track_x[6] = 128;
				track_x[7] = 256;
				track_x[8] = 640;
				track_y[0] = 0;
				track_y[1] = 96;
				track_y[2] = 0;
				track_y[3] = -64;
				track_y[4] = 0;
				track_y[5] = 32;
				track_y[6] = 0;
				track_y[7] = -64;
				track_y[8] = 0;

				track_width_one = 0;
				for (i = 0; i < track_x.length; i++) track_width_one += track_x[i];

				x_bound = s_w >> 1;
				shoot_bound = track_width_one - track_x[track_x.length - 1] + 100 - s_w + x_bound - 10;
				track_x_sum = track_width_one;

				track_width = track_width_one * rounds_count;
				track_width_one = track_width_one * (rounds_count - 1) + 32;

				tracks_total = track_x.length * rounds_count;

				a_x_range = track_width - s_w;                                        

				fT = new Frame[3];
				fSn = new Frame[8];
				fTree = new Frame[1];
				fFlag = new Frame[2];
				for (i = 0; i < fT.length; i++) fT[i] = gf("tr" + i);
				for (i = 0; i < fSn.length; i++) fSn[i] = gf("sn" + i);
				for (i = 0; i < fTree.length; i++) fTree[i] = gf("tree" + i);
				for (i = 0; i < fFlag.length; i++) fFlag[i] = gf("flag" + i);

				y_bound_bottom = s_h - 8;
				if (s_h > 100) y_bound_bottom -= 8;
				if (s_h > 130) y_bound_bottom -= 8;

				y_bound_top = y_bound_bottom - 10;
				if (s_h > 100) y_bound_top -= 6;
				if (s_h > 130) y_bound_top -= 6;

//#if !T610
				fBg = gf("bg0");
				y_bg_top = y_bound_top - fBg.fh - 8;
//#endif
				fChess = gf("chess");
				fTarget = gf("target");
				fSign = gf("csh");
				fMeter = gf("mtr");
				fMeterred = gf("mtrred");
				fHeart = gf("heart");
				fAmmo = gf("ammo");

				readAnimation("a_b",7);

				man = new Dynamic();
				man.init(0,0,"m",false);
				if (needGhost)
				{
					ghost = new Dynamic();
					ghost.init(0,0,"mg",true);
				}

				start_x = 0;
				start_y = y_bound_bottom;
				state_delay = 1000;
			}
			hp = null;
			System.gc();

           	enqueue_abc(0);
           	enqueue_abc(1);

			if (!loadImages(false))
			{
				endGame();
				return;
			}
			needLoadingIndicator = false;
			font = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL);
			if (needGhost)
			{
	        	ghost_data = new byte[GHOST_DATA_SIZE];
				ghost_data_count = readGhostLocal(game_id,ghost_data);
				if (ghost_data_count == 0)
				{
					ghost = null;
					ghost_data = null;
				}
			}
			resourcesLoaded = true;
			restart();
		}
		catch(Exception ex)
		{
//			ex.printStackTrace();
		}
    }

    void restart()
    {
    	try
    	{
			ghost_data_w = null;
			ghost_data_count_w = ghost_data_ptr = ghost_data_ptr_w = 0;
			System.gc();

	   	   	switch(state)
   		   	{
			case STATE_SKIJUMP_RUN:
				points = 100;
				distance = total_points = 0;
	           	break;
			case STATE_SKATER_RUN:
				man.state = STATE_SKATER_RUN;
				if (ghost != null)
				{
					ghost.state = STATE_SKATER_RUN;
				}
    	       	break;
			case STATE_BIATHLON_RUN:
				man.state = STATE_BIATHLON_RUN;
				man.target_y = y_bound_bottom - 32;

				if (ghost != null)
				{
					ghost.state = STATE_BIATHLON_RUN;
					ghost.target_y = y_bound_bottom - 32;
				}
			}
			man.restart();
			if (ghost != null) ghost.restart();

			rounds_passed = 0;
			ghost_data_w = new byte[GHOST_DATA_SIZE]; // alloc memory for ghost data
			a_x_d = a_y_d = 0;
			time_start = 0;
			go_delay = 20;
			go_index = 0;
			paused = false;
    		time_start = 0;
    		time_current = 0;
    		time_finish = 0;
    		ghost_time = 0;
    		ghost_time_w = 0;
			frames_passed = 0;
			isKeyPressed = false;
	    	initOK = true;
//	    	m("restarted");
		}
		catch(Exception ex)
		{
		}
    }

    void readAnimation(String prefix,int a) throws Exception
    {
    	anims = new int[a][];
    	for (i = 0; i < a; i++)
    	{	
    		str = gp(prefix + i);
    		if (str != null)
    		{
    			v1 = parse(str);
    			anims[i] = new int[((Integer)v1.elementAt(0)).intValue()];
    			for (j = 0; j < anims[i].length; j++) anims[i][j] = ((Integer)v1.elementAt(j + 1)).intValue();
		    	v1 = null;
    		}
    	}
    }

    static long time_start, time_current, time_finish, ghost_time, ghost_time_w, time_extra, time_total;
    static long frames_passed;

    static boolean isKeyPressed;
    protected void keyPressed(int keyCode)
    {
	    key_action = action = keyCode;
	    isKeyPressed = true;
//#if !Nokia
	    game_action = getGameAction(keyCode);
	    switch(game_action)
	    {
	    	case Canvas.UP: 	action = KEY_NUM2; break;
	    	case Canvas.DOWN: 	action = KEY_NUM8; break;
	    	case Canvas.LEFT: 	action = KEY_NUM4; break;
	    	case Canvas.RIGHT:  action = KEY_NUM6; break;
	    	case Canvas.FIRE: 	action = KEY_NUM5; 
	    }
	    key_action = action;
//#endif
	}

    protected void keyReleased(int keyCode)
    {
		isKeyPressed = false;
	}

	static int ghost_action = 0;
	static void readGhost()
	{
		try
		{
			if (ghost_data_count > ghost_data_ptr)
			{
				ghost_action =  NO_ACTION;
				tt = frames_passed;
				i = ((ghost_data[ghost_data_ptr] & 0x000000FF) << 8) | (ghost_data[ghost_data_ptr + 1] & 0x000000FF);
		
				if (ghost_time + i <= tt)
				{
					ghost_time = tt;

					g_action =   (ghost_data[ghost_data_ptr + 3] & 0x000000FF) | 
								((ghost_data[ghost_data_ptr + 2] & 0x000000FF) << 8);


					j = (g_action >> 4) & 0x0000000F;

					if (ghost != null)
					{
						if (j != ghost.j_wind_dest)
						{
							ghost.j_wind_dest = j;
	    					ghost.j_wind_d = ghost.j_wind_dest - ghost.j_wind;
    						if (ghost.j_wind_d > 8 || (ghost.j_wind_d < -8)) 
    							ghost.j_wind_d = - ghost.j_wind_d;
		    				ghost.j_wind_d = ghost.j_wind_d > 0 ? 1 : -1;
		    			}

						ghost.j_wind_power_dest = (g_action >> 8) & 0x00000003;
						ghost.jw = 50 * ghost.j_wind_power_dest / 3;
						ghost.j_i1 = (g_action >> 10) & 0x00000007;
						ghost.j_i2 = (g_action >> 13) & 0x00000007;
						ghost.processed = true;
					}
					ghost_action = NO_ACTION;
					switch (g_action & 0x0000000F)
					{
//						case 1:  ghost_action = Canvas.KEY_NUM0; break;
//						case 2:  ghost_action = Canvas.KEY_NUM1; break;
						case 3:  ghost_action = Canvas.KEY_NUM2; break;
//						case 4:  ghost_action = Canvas.KEY_NUM3; break;
						case 5:  ghost_action = Canvas.KEY_NUM4; break;
						case 6:  ghost_action = Canvas.KEY_NUM5; break;
						case 7:  ghost_action = Canvas.KEY_NUM6; break;
//						case 8:  ghost_action = Canvas.KEY_NUM7; break;
						case 9:  ghost_action = Canvas.KEY_NUM8; break;
//						case 10: ghost_action = Canvas.KEY_NUM9; break;
						case 11: ghost_action = Canvas.KEY_STAR; break;
//						case 12: ghost_action = Canvas.KEY_POUND; break;
					}
					ghost_data_ptr += 4;
				}
			}
		}
		catch(Exception ex){}
	}

	static void writeGhost(boolean processed)
	{
		try
		{
			if (ghost_data_w != null)
			if (ghost_data_count_w == 0 && processed)
			{
				i = (int)(frames_passed - ghost_time_w);
				ghost_time_w = frames_passed;
				// skip empty periods
				while (i > 0xFFFF)
				{
					ghost_data_w[ghost_data_ptr_w] = (byte)0xFF;
					ghost_data_w[ghost_data_ptr_w + 1] = (byte)0xFF;
					ghost_data_w[ghost_data_ptr_w + 2] = (byte)0;
					ghost_data_w[ghost_data_ptr_w + 3] = (byte)0;
					i -= 0xFFFF;
				}
				ghost_data_w[ghost_data_ptr_w] = (byte)((i & 0xFF00) >> 8);
				ghost_data_w[ghost_data_ptr_w + 1] = (byte)(i & 0xFF);

				g_action = 0;
				switch(key_action)
				{
//					case Canvas.KEY_NUM0:	
//						g_action = 1; 
//						break;
//					case Canvas.KEY_NUM1:	
//						g_action = 2; 
//						break;
					case -1:
					case Canvas.KEY_NUM2:	
						g_action = 3; 
						break;
//					case Canvas.KEY_NUM3:	
//						g_action = 4; 
//						break;
					case -3:				
					case Canvas.KEY_NUM4:  
						g_action = 5; 
						break;      
					case -5:
					case -6:
					case Canvas.KEY_NUM5:	
						g_action = 6; 
						break;
					case -4:
					case Canvas.KEY_NUM6:	
						g_action = 7; 
						break;
//					case Canvas.KEY_NUM7:	
//						g_action = 8; 
//						break;
					case -2:
					case Canvas.KEY_NUM8:	
						g_action = 9; 
						break;
//					case Canvas.KEY_NUM9:	
//						g_action = 10;
//						break;
					case -7:
					case Canvas.KEY_STAR:	
						g_action = 11; 
						break;
//					case Canvas.KEY_POUND:	
//						g_action = 12; 
//						break;
				}

				g_action |= man.j_wind_dest << 4;
				g_action |= man.j_wind_power_dest << 8;
				g_action |= man.ji1 << 10;
				g_action |= man.ji2 << 13;


				ghost_data_w[ghost_data_ptr_w + 2] = (byte)((g_action & 0xFF00) >> 8);
				ghost_data_w[ghost_data_ptr_w + 3] = (byte)(g_action & 0x00FF);
				ghost_data_ptr_w += 4;
			}
		}
		catch(Exception ex)
		{
			ghost_data_w = null;
			ghost_data_count_w = ghost_data_ptr_w = 0;
		}
	}

    static void pause()
    {
    	paused = true;
    	state_old = state;
		action = key_action = NO_ACTION;
		m_paused = true;
		m_state = state;
		menuLevel = 0;
		m_time_left = System.currentTimeMillis();
		midlet.main.returnMenu();
    }

    static void finish_skater_run()
    {
		state = STATE_SKATER_RUN_FINISH;
		state_delay = 40;
		go_delay = 20;
		go_index = 3;

		time_finish = time_total = time_current;
		total_points = (int)(8000 - (time_total - 40000) / 10);
		if (total_points < 0) total_points = 0;
		ghost_data_count_w = ghost_data_ptr_w;
    }

    static void finish_biathlon_run()
    {
		go_delay = 20;
		go_index = 3;

		time_finish = time_current;
		time_extra = man.missed * 5000;
		time_total = time_finish + time_extra;

		total_points = (int)(9000 - (time_total - 90000) / 10);
		if (total_points < 0) total_points = 0;
		ghost_data_count_w = ghost_data_ptr_w;
    }

    static void update_skater_run()
    {
    	readGhost();
    	if (ghost != null) ghost.update_skater_run(ghost_action);
    	writeGhost(man.update_skater_run(key_action));

    	rel_dx = man.x - a_x_d;

    	if ((s_w - x_bound < rel_dx) && (man.dx > 0)) a_x_d += man.dx;
    	if (a_x_d > a_x_range) a_x_d = a_x_range;
		frames_passed++;
    }    

    static void update_biathlon()
    {
    	readGhost();
    	if (ghost != null) ghost.update_biathlon(ghost_action);
    	writeGhost(man.update_biathlon(key_action));

    	if (man.state == STATE_BIATHLON_SHOOT) action = key_action = NO_ACTION;


    	rel_dx = man.x - a_x_d;
    	rel_dy = start_y - man.y - a_y_d;

    	if ((x_bound > rel_dx) && (man.dx < 0))
    	{
    		a_x_d += man.dx;
    	}

    	if ((s_w - x_bound < rel_dx) && (man.dx > 0))
    	{
    		if ((man.x % track_x_sum > shoot_bound) && man.shootEnabled){}
    		else 
    		if ((man.state == STATE_BIATHLON_RUN) || (man.state == STATE_BIATHLON_RUN_FINISH)) a_x_d += man.dx;
    	}

    	if ((y_bound_top > rel_dy) && (man.dy > 0))
    	{
    		a_y_d -= man.dy;
    	}
    	if ((y_bound_bottom < rel_dy) && (man.dy < 0))
    	{
    		a_y_d -= man.dy;
    	}

		frames_passed++;
    }

    void update_skijump()
    {

    	if (ghost != null)
    	{
	    	readGhost();
    		ghost.update_skijump_1(ghost_action);
    	}
    	man.update_skijump_1(key_action);

   		writeGhost(man.processed);
		frames_passed++;
		key_action = action = NO_ACTION;

    	if (ghost != null) ghost.update_skijump_2();
    	man.update_skijump_2();


		if (go_delay > 0)
		{
			if (--go_delay <= 0) 
			{
				if (go_index < 2)
				{
					go_delay = 20;
					go_index++;
					if ((go_index >= 2) && (man.j_state == 0))
					{
						man.j_state = 1;
						man.j_t1 = 80;
						man.j_ay = 4096;

						if (ghost != null)
						{
							ghost.j_state = 1;
							ghost.j_t1 = 80;
							ghost.j_ay = 4096;
						}
					}
					else
					{
					}	
				}
				if (go_index >= 3)
				{
					if (man.j_state == 18)
					{
						menuLevel = 9;
						returnMenu();
						return;
					}
					else
					{
						ghost_data_count_w = ghost_data_ptr_w;
						go_delay = 0;
						state_delay = 40;
						state = STATE_SKIJUMP_RUN_SCORES;
					}
				}
			}
		}

    	if (ghost != null) ghost.update_skijump_3();
    	man.update_skijump_3();

    	rel_dx = man.j_x - a_x_d;
    	rel_dy = man.j_y - a_y_d;

    	if (x_bound < rel_dx) 
    	{
    		if ((man.j_state == 18) && (man.j_v > 0)) a_x_d += 2;
    		else a_x_d += man.j_dx;
    	}

    	if (a_x_d > a_x_range) a_x_d = a_x_range;

    	if (y_bound_bottom < rel_dy)
    	{ 
    		if ((man.j_state == 18) && (man.j_v > 0)) a_y_d += 2;
    		else a_y_d += man.j_dy;
    	}

		y_bg_top = ((s_h - fBg.fh) >> 1) - (a_y_d >> 3) + 10;
	}

	void updateEditor()
	{
		try
		{
		    switch (action)
		    {
				case -3:
				case Canvas.KEY_NUM4:if (--editX < 0) editX = 10;
						break;
				case -4:
				case Canvas.KEY_NUM6:if (++editX > 10) editX = 0;
						break;
				case -1:							
				case Canvas.KEY_NUM2:if (--editY < 0) editY = 3;
						break;
				case -2:
				case Canvas.KEY_NUM8:if (++editY > 3) editY = 0;
						break;
				case -6:
				case -5:
				case Canvas.KEY_NUM5:
						ch = letters.charAt(editY * 11 + editX);
						if (ch == '_')
						{
							if (idx > 0) idx--;
						}
						else
						{
							if (ch != '#')
							{
								editText[idx] = ch;
								if (idx + 1 < editText.length) idx++;
								else ch = '#';
							}

							if (ch == '#')
							{
								if (new String(editText).trim().length() > 0)
								{
									state = STATE_EDITOR_FINISH;	
									state_delay = 2;
								}
							}	
						}
						break;
				case NO_ACTION:break;
				case -7:
				case KEY_STAR:
						action = NO_ACTION;
						editBack();
			}
		}
		catch(Exception ex){}
        action = NO_ACTION;
	}

	void updateMenu()
	{
		if (vMenu != null)
		{
			try
			{
			    switch (action)
			    {
					// left
					case -3: // 7210
					case Canvas.KEY_NUM4:
//							menuIndex -= menuRange;
							break;
					// right
					case -4: // 7210
					case Canvas.KEY_NUM6:
//							menuIndex += menuRange;
							break;
					// up
					case -1: // 7210
					case Canvas.KEY_NUM2:
							if (isPointer) menuIndex --;
							else menuDisp -= menuRange;
							break;
					// down
					case -2: // 7210
					case Canvas.KEY_NUM8:
							if (isPointer) menuIndex ++;
							else menuDisp += menuRange;
							break;
					// select
					case -5: // 60
					case -6: // 7210
					case Canvas.KEY_NUM5:
							menuOk(menuIndex);
							break; 	
					case NO_ACTION:break;
					// exit
					case -7: // 7210
					case KEY_STAR:
					        action = key_action = NO_ACTION;
							if (menuLevel != 0)
							{
								resourcesLoaded = false;
								menuBack(menuLast < 0 ? 0 : menuLast);
							}
				}
				if (isPointer)
				{
					if (menuIndex < 0) menuIndex = 0;
					if (menuIndex >= vMenu.size()) menuIndex = vMenu.size() - 1;
					j = menuSize - vMenuName.size();
					for (i = 0, n = 0; i < vMenu.size(); i++)
					{
						v = (Vector)vMenu.elementAt(i);
			
						if (i == menuIndex) // correct menuDisp to scroll menu
						{
							while(n < menuDisp) menuDisp --;
							while(menuDisp + menuRange <= (n + v.size() - 1) && (menuDisp + menuRange <= j)) 
								menuDisp ++;
						}
						n += v.size();
					} 
				}
				else
				{
					if (menuDisp + menuRange > vMenu.size()) menuDisp = vMenu.size() - menuRange;
					if (menuDisp < 0) menuDisp = 0;
				}
			}
			catch(Exception ex){}
		}
        action = key_action = NO_ACTION;
	}

    // graphics methods *******************************************************************************

    static Graphics gd = null;

    static void createImage(int index, String resourceName) throws IOException
    {
		img[index] = Image.createImage(resourceName);
    }

    static int getImageWidth(int index)
    {                
		return img[index].getWidth();
    }

    static int getImageHeight(int index)
    {                
		return img[index].getHeight();
    }

    static void setClip(int x,int y,int w,int h)
    {
    	gd.setClip(x,y,w,h);
    }

    static void drawImage(int index,int x,int y)
    {
    	gd.drawImage(img[index],x,y,20);
    }

    static void setColor(int color)
    {
		gd.setColor(color);    	
    }

    static void fillRect(int x, int y, int w, int h)
    {
    	gd.fillRect(x,y,w,h);
    }

    static void setFont(Font font)
    {
    	gd.setFont(font);
    }

    static void drawLine(int x1, int y1, int x2, int y2)
    {
    	gd.drawLine(x1, y1, x2, y2);
    }

    static void drawString(String str, int x, int y, int pos)
    {
    	gd.drawString(str,x,y,pos);
    }

    static void drawRect(int x1, int y1, int x2, int y2)
    {
    	gd.drawRect(x1,y1,x2,y2);
    }
    //

    static long tt=0;
    static int state_delay = 0;
    static int go_delay = 0, go_index = 0;

    boolean isBoard = false;
    static int pstate = -1, state_old;
    static boolean paused = false;

    static boolean isPainting = false;

    public void paint(Graphics g)
    {
    	doPaint(g);
    }

    public void doPaint(Graphics gd)
    {

	    isPainting = true;
	    Frame.cnt = 0;

		tt = System.currentTimeMillis();
		time_current = 0;
		if (time_start > 0) time_current = tt - time_start;
		isBoard = false;
		this.gd = gd;
    	try
    	{
	    	setFont(font);
			setClip(0,0,s_w,s_h);
	    	pstate = paused ? state_old : state;

			if (running && (initOK || (pstate == STATE_INTRO) || (pstate == STATE_LOGO)))
			{
				switch (pstate)
				{
				case STATE_SKIJUMP_RUN:
				case STATE_SKIJUMP_RUN_FINISH:
					setColor(0x88AAEE);
					fillRect(0,0,s_w,y_bg_top);
					setColor(0xFFFFFF);
					fillRect(0,fBg.fh + y_bg_top,s_w,s_h);
					x = (a_x_d >> 3) % fBg.fw;				// background
    		     	for (i = - x; i < s_w; i+= fBg.fw) 
						fBg.draw(i,y_bg_top);
					y = y_bg_top + fBg.fh - fTree[0].fh + 10;
					for (i = 0, j = -2; i < track_width; i += 40, j = -j)
					{
						x = i - (a_x_d >> 2);
						if ((x > - fTree[0].fw) && (x <= s_w))
							fTree[0].draw(x,y + j);
					}
                    setColor(0xffFFFF);
                    //////////////////////////////////////////////////////////////////////////////////////
                    for (i = 0, j = 0; i < track_x[0]; i += fT[0].fw, j += 34)
                    {
                    	x = i - a_x_d;
                    	y = j + start_y - a_y_d;
                    	if ((x >= - fT[0].fw) && (x <= s_w))
                    	{
                    		setClip(0,0,s_w,s_h);
                    		fillRect(x, y + 34, fT[0].fw, s_h - y - 34);
							fT[0].draw(x,y);
						}
                    }
                    //////////////////////////////////////////////////////////////////////////////////////
                   	x = i - a_x_d;
                   	y = j + start_y - a_y_d;
                   	if ((x >= - fT[1].fw) && (x <= s_w))
                   	{
                   		setClip(0,0,s_w,s_h);
                   		fillRect(x, y + 34, fT[0].fw - 10, s_h - y - 34);
						fT[1].draw(x,y);                    	
					}
					j += Dynamic.J_HEIGHT + 7;

					i += track_x[1] + track_x[2];
					w2 = i + track_x[3];
					for (k = 0, i2 = 0; i < w2; i += fT[2].fw, j += 16, k = 1 - k, i2 += 10) // diagonal landing
					{
                    	x = i - a_x_d;
                    	y = j + start_y - a_y_d;

                    	if ((x >= - fT[2].fw) && (x <= s_w) && (y <= s_h))
                    	{
                    		setClip(0,0,s_w,s_h);
                    		fillRect(x, y + 16, fT[2].fw, s_h - y - 16);
							fT[2].draw(x,y);
						}
                    	if ((k == 0) && (x >= - 28) && (x <= s_w))
                    	{
								fSign.draw(x,y - 12);
        	            		intToString(i2,0,3);
    	                		buf[3] = 'm';
		                   		drawChars(0,4,x + 1, y - 8,2);
						}
					}
					w2 = i + track_x[4];
					for (; i < w2; i += fT[3].fw)	// horizontal landing
					{
                    	x = i - a_x_d;
                    	y = j + start_y - a_y_d;
                    	if ((x >= - fT[3].fw) && (x <= s_w))
                    	{
                    		setClip(0,0,s_w,s_h);
                    		fillRect(x, y + 30, fT[2].fw, s_h - y - 30);
							fT[3].draw(x,y);
						}
					}
            		setClip(0,0,s_w,s_h);
					if (ghost != null)
					{
						ghost.drawSJ();
						drawGhostName(ghost.j_x - a_x_d + 8, ghost.y - a_y_d - 24, 0xFF1020);
					}
            		setClip(0,0,s_w,s_h);
					man.drawSJ();

					abci = 0;
                    str = text[41]; // wind

                    x = s_w - getStringWidth(str);
                    y = 1;

                    x1 = s_w - fMeter.fw - 4;
                    y1 = y + 11;

                    x2 = x1 + 6;
                    y2 = y1 + 16;

//#if Size_0
            	    x -= 10;

	                x2 = s_w - 8;
                    y2 = 1;

        	        x1 = x2 - 20;
    	            y1 = y + 10;
//#endif
                    drawString(str,x,y);

					setClip(0, 0, s_w, s_h);
					fMeter.draw(x1,y1);

					x1 += 8;
					y1 += 8;

					w2 = x1 + (cos[man.j_wind] >> 5);
					h2 = y1 + (sin[man.j_wind] >> 5);

					setClip(0,0,s_w,s_h);

					setColor(0xFF0000);
					drawLine(x1, y1, w2, h2);
					fMeterred.draw(w2 - 2,h2 - 2);

					setClip(0, 0, s_w, s_h);
					fChess.draw(x2,y2);
					fBoard.draw(x2,y2 + 8);

					for (y = 4; y < 50; y += 14)
					{
						fTarget.draw(x2,y + y2, x2,y2,6,50 - man.j_wind_power);
					}

					if (ghost != null)
						if (m_ghost != null) drawString(m_ghost,2,2);
						else drawString(text[30],2,2); // ghost

					break;
				case STATE_SKIJUMP_RUN_SCORES:
					y = s_h >> 1;

					drawBgm();

					drawString(text[31],2,y - 24); // length
					intToString(distance,0,3);
					drawChars(0,3,s_w - 22,y - 27,1);

					drawString(text[32],2,y - 8); // style
					intToString(points,0,3);
					drawChars(0,3,s_w - 22,y - 10,1);

					setColor(0xA0A000);
					setClip(0,0,s_w,s_h);
					drawLine(2,y + 4,s_w - 2,y + 4);

					drawString(text[33],2,y + 11); // score
					intToString(total_points,0,3);
					drawChars(0,3,s_w - 22,y + 9,1);
					break;

				case STATE_SKATER_RUN:
				case STATE_SKATER_RUN_FINISH:

					setClip(0,0,s_w,s_h);
					setColor(0x88AAEE);

					y = s_h - 50 - fT[0].fh - fTarget.fh - fBg.fh + 40;
					fillRect(0,0,s_w,y);

	    	     	for (i = 0; i < s_w; i+= fBg.fw) fBg.draw(i,y);

					y += fBg.fh - 40;

					x = (a_x_d >> 2) % fTarget.fw;
	    	     	for (i = - x; i < s_w; i+= fTarget.fw) fTarget.draw(i,y);

					y += fTarget.fh;
					x = (a_x_d >> 2) % (fT[0].fw + fT[1].fw);	
	    	     	for (i = - x; i < s_w; i+= fT[0].fw + fT[1].fw)
	    	     	{
	    	     		fT[0].draw(i, y);
	    	     		fT[1].draw(i + fT[0].fw,y);
	    	     	}
					y += fT[0].fh;

					setClip(0,0,s_w,s_h);
					setColor(0xF8F8FF);
					fillRect(0,y,s_w,60);

					y -= 2;

					x = (a_x_d >> 2) % fSnow.fw;	
	    	     	for (i = - x; i < s_w; i+= fSnow.fw) 
						fSnow.draw(i,y);

					x = track_width - a_x_d;
					y += 10;

					if (x < s_w)
					fChess.draw(x,y + 4);

					x = (fChess.fw >> 1) - a_x_d;
					if (x + fChess.fw > 0)                                                                             
					{
						fChess.draw(x, y + 4);
					}
//#if Nokia
					y += man.frm[0].fh - 12;
//#else
					y += man.frm_up[0].fh - 12;
//#endif

					if (ghost != null)
					{
						y -= 22;
						start_y = y;
						ghost.drawBSS();	
						drawGhostName(ghost.x - a_x_d, ghost.ty, 0xFFFFFF);

						y += 24;
						start_y = y;
						man.drawBSS();	
						y -= 2;
					}
					else
					{
						start_y = y;
						man.drawBSS();	
					}

					setClip(0, 0, s_w, s_h);
					y -= 10;
					x = a_x_d % fAmmo.fw;			
	    	     	for (i = - x; i < s_w; i+= fAmmo.fw) 
						fAmmo.draw(i,y);

					y += fAmmo.fh;

					setClip(0,0,s_w,s_h);
					setColor(0xD7FFF6);
					fillRect(0,y,s_w,s_h - y);

					y -= fSign.fh;
					w = fAmmo.fw << 3;
                    for (x = - fSign.fw >> 1, i = 0; x < track_width; x += w, i += 100)
                    {
                    	if (x > 0 && (x + fSign.fw >= a_x_d) && (x <= (a_x_d + s_w)))
                    	{
                    		fSign.draw(x - a_x_d,y);

                    		if (i < 1000)
                    		{
        	            		intToString(i,0,3);
    	                		buf[3] = 'm';
                    		}
                    		else
                    		{
                    			buf[0] = 'g';
                    			buf[1] = 'o';
                    			buf[2] = 'a';
                    			buf[3] = 'l';
                    		}
	                   		drawChars(0,4,x - a_x_d + 1, y + 4,2);
                    	}
                    }
					setClip(0,0,s_w,s_h);

					isBoard = true;
					break;
				case STATE_SKATER_RUN_SCORES:
					y = s_h >> 1;

					drawBgm();
					drawString(text[34],2,y - 8); // time
					timeToString(time_finish);
					drawChars(0,8,s_w - 51,y - 10,1);

					setColor(0xA0A000);
					setClip(0,0,s_w,s_h);
					drawLine(2,y + 4,s_w - 2,y + 4);

					drawString(text[33],2,y + 11); // score
					intToString(total_points,0,4);
					drawChars(0,4,s_w - 29,y + 9,1);
					break;
				case STATE_BIATHLON_RUN_SCORES:
					y = s_h >> 1;

					drawBgm();
					drawString(text[34],2,y - 29); // time
					timeToString(time_finish);
					drawChars(0,8,s_w - 51,y - 31,1);

					drawString(text[35],2,y - 12); // missed
					intToString(man.missed,0,2);
					drawChars(0,2,s_w - 15,y - 14,1);

					setColor(0xA0A000);
					setClip(0,0,s_w,s_h);
					drawLine(2,y,s_w - 2,y);

					drawString(text[36],2,y + 5); // result
					timeToString(time_total);
					drawChars(0,8,s_w - 51,y + 3,1);

					drawString(text[33],2,y + 22); // score
					intToString(total_points,0,4);
					drawChars(0,4,s_w - 29,y + 20,1);
					break;
				case STATE_BIATHLON_RUN:
					switch (man.state)
					{
					case STATE_BIATHLON_RUN:
					case STATE_BIATHLON_RUN_FINISH:
						setColor(0x88AAEE);

//#if T610
						fillRect(0,0,s_w,y_bg_top + 70);
						setColor(0xFFFFFF);
						fillRect(0,y_bg_top + 70,s_w,s_h);
//#else

						fillRect(0,0,s_w,y_bg_top);
						setColor(0xFFFFFF);

						fillRect(0,y_bg_top + fBg.fh,s_w,s_h);

						x = (a_x_d >> 3) % fBg.fw;				// background

	    		     	for (i = - x; i < s_w; i+= fBg.fw) 
							fBg.draw(i,y_bg_top);
//#endif
						y = y_bound_bottom - fTree[0].fh - 16;
						for (i = (a_x_d >> 1), j = -2; i < track_width; i += 40, j = -j)
						{
							x = i - a_x_d;
							if ((x > - fTree[0].fw) && (x <= s_w))
								fTree[0].draw(x,y + j);
						}
						for (k = 0; k < 3; k++)
						if (k == 1)
						{
							if (ghost != null) 
							{
								if ((ghost.state == STATE_BIATHLON_RUN) || (ghost.state == STATE_BIATHLON_RUN_FINISH))
								{
									ghost.y += 2;
									ghost.x = ghost.x % track_x_sum;
									for (i = 0; i < rounds_count; i++, ghost.x += track_x_sum)
									{
										ghost.drawBSS();
										drawGhostName(ghost.x - a_x_d, ghost.ty, 0xFF1020);
									}
									ghost.y -= 2;
								}
								man.y -= 2;
								man.drawBSS();
								man.y += 2;
							}
							else man.drawBSS();
						}
						else
						{
							distance = 0;
							x2 = y2 = idx = 0;
							setColor(0xFFFFFF);
							for (i = 0,itotal = 0; itotal < tracks_total; i++,itotal++)
							{
								if (i >= track_x.length) i = 0;

								x1 = x2;
								y1 = y2;
								x2 += track_x[i];
								y2 += track_y[i];
			
								if (x2 >= a_x_d && (x1 <= (a_x_d + s_w)))
								{
									n = 0;
									dy = 12;
									if (track_y[i] > 0)
									{
										n = 1; 
										dy = 19;
									}
									if (track_y[i] < 0)
									{
										n = 2; 
										dy = 12;
									}
				
									y = y1;
									w = fT[n].fw;
					
									for (j = x1,x = 0; j < x2; j += w, x += w)
									{
										if (j + w >= a_x_d && (j <= (a_x_d + s_w)))
										{
											if (k == 0)
											{
												fT[n].draw(j - a_x_d,start_y - a_y_d - dy - y,x1 - a_x_d,0,x2 - x1,s_h);
												setClip(0,0,s_w,s_h);
												fillRect(j - a_x_d,start_y - a_y_d - dy - y + fT[n].fh,w,32);
				
												fSn[idx].draw(j - a_x_d,start_y - a_y_d - y - 12);
												fSn[idx + 4].draw(j - a_x_d + 8,start_y - a_y_d - dy - y + fT[n].fh);
							
												if (i == 0 && (x == 0))
												{
													fChess.draw(j - a_x_d,start_y - a_y_d - y - 10);
												}
	   	
												if (0 == (distance & 127))
												{
													fFlag[0].draw(j - a_x_d + 12, start_y - a_y_d - y - 12 - fFlag[0].fw);
												}
											}
											if (k == 2)
											{
												if (0 == (distance & 127))
												{
													setClip(0,0,s_w,s_h);
													fFlag[1].draw(j - a_x_d + 2,start_y - a_y_d - dy - y + fT[n].fh - 10);
												}
											}
										}
										if (track_y[i] < 0) y -= 8;
										if (track_y[i] > 0) y += 8;
						
										distance += w;
										idx = (++idx) & 3;
									}
								}
								else
								{
									distance += track_x[i];
								}
							}
						} // if k
						isBoard = true;
                        break;
					case STATE_BIATHLON_SHOOT:
					case STATE_BIATHLON_SHOOT_FINISH:
						setColor(0x88AAEE);
//#if T610
						fillRect(0,0,s_w,y_bg_top + 70);
						setColor(0xFFFFFF);
						fillRect(0,y_bg_top + 70,s_w,s_h);
//#else
						fillRect(0,0,s_w,y_bg_top);
						setColor(0xFFFFFF);
						fillRect(0,y_bg_top + fBg.fh,s_w,s_h);

						x = (a_x_d >> 3) % fBg.fw;				// background

		    	     	for (i = - x; i < s_w; i+= fBg.fw) 
							fBg.draw(i,y_bg_top);
//#endif
						y = y_bound_bottom - fTree[0].fh - 16;
						for (i = 0, j = -2; i < track_width; i += 40, j = -j)
						{
							if ((i > - fTree[0].fw) && (i <= s_w))
								fTree[0].draw(i,y + j);
						}

						y = s_h - fMeter.fh - 16;
						h = man.s_v >> 5;
						fMeter.draw(7,y);
						fMeterred.draw(7,y + 8,0,y + 18 - h - h,s_w,h + h);
						setClip(0,0,s_w,s_h);
						fHeart.draw(2,y - fHeart.fh - 6,man.heart_index);

						for (i = 0, x = 0; i < 5; i++, x += fAmmo.fw)
						{
							if (i < man.aim_n) fAmmo.draw(8 + x,6,1);
							else fAmmo.draw(8 + x,6);
						}

						y = man.target_y - (fTarget.fh >> 1);
						for (i = 0, x = ((s_w - fTarget.fw) >> 1) - fTarget.fw - fTarget.fw; i < man.targets.length; i++, x += fTarget.fw)
						{
							if (man.targets[i] == -1) fTarget.draw(x,y,1);
							if (man.targets[i] == 0) fTarget.draw(x,y,0);
							if (man.targets[i] > 0) fTarget.draw(x,y,2);
						}

						setClip(0,0,s_w,s_h);

						if (man.state == STATE_BIATHLON_SHOOT)
						{
							x = (s_w >> 1) + fTarget.fw * (man.aim_n - 2) - (fSign.fw >> 1) + man.aim_x;
							y = man.target_y - man.aim_y - (fSign.fh >> 1);
							fSign.draw(x,y);
						}
			
						isBoard = true;
					}
					if (ghost != null)
					{
						if ((ghost.state == STATE_BIATHLON_SHOOT) || (ghost.state == STATE_BIATHLON_SHOOT_FINISH))
						{
							setClip(0,0,s_w,s_h);							
							str = (m_ghost != null) ? m_ghost : text[30]; // ghost
							drawString(str + text[37],2,s_h - 10); // shoots
						}
					}
					break;

				case STATE_EDITOR:
				case STATE_EDITOR_FINISH:
					drawBgm();

					w1 = ew * 11;

					x = ((s_w - w1) >> 1);
					y = (s_h - 62) >> 1;

					str = menuName;
					ch = letters.charAt(editY * 11 + editX);
					if (ch == '_') str = text[9]; // back
					if (ch == '#') str = text[38]; // ok

					drawString(str,x,y + 2);

					setClip(0,0,s_w,s_h);
					setColor(0x8080B0);

					fillRect(x + w1 + ew * (idx - editText.length) - 1,y + 1,ew,10);

					for (i = 0, j = x + w1 - editText.length * ew; i < editText.length; i ++, j += ew)
					{
						buf[0] = editText[i];
						drawChars(0,1,j,2 + y);
					}

					for (j = 0; j < 4; j++)
						for (i = 0; i < 11; i++)
						{
							buf[0] = letters.charAt(j * 11 + i);
							drawChars(0,1,x + i * ew, j * 12 + y + 14);
						}

					setClip(0,0,s_w,s_h);
					 
					setColor(0x60B0A0);
					drawRect(editX * ew + x - 1, editY * 12 + y + 13,ew,11);

					setColor(0x8080B0);
					drawRect(x - 2,y + 12,w1 + 2,49);
					break;
				case STATE_PLACE:
					drawBgm();
					w1 = getStringWidth(message);
					drawString(message,(s_w - w1) >> 1, (s_h - 10) >> 1);
					break;

				case STATE_INTRO:
					setColor(0xFFFFFF);
					fillRect(0,0,s_w,s_h);
					if (fBg != null) fBg.draw((s_w - fBg.fw) >> 1,(s_h - fBg.fh) >> 1);
					break;
				case STATE_LOGO:
					drawLogo(false);
					break;
				} // switch by pmode

				if (state == STATE_MENU)
				{
					if (!paused) drawLogo(true);
					else drawRast();

					w1 = menuItemWidth;

					if (!isPointer)
					{
						setClip(0,0,s_w,s_h);
						setColor(0x000040);
						fillRect(2,menuTop - 4, s_w - 4,s_h - menuTop + 2);
					}     
					if (vMenu != null)
    				if (vMenu.size() > 0)
    				{
						y = (menuIndex - menuDisp) * menuHeight + menuTop;

			            h1 = 0;

			            int totalMenuHeight = (vMenu.size() + vMenuName.size()) * menuHeight + menuTop + menuTop;
		            	if (totalMenuHeight < s_h)
		        	    {
		    	        	h1 = ((s_h - totalMenuHeight) >> 1) + 8;
			            }
						if (!showLogo)
						{
							x = (s_w - menuWidth) >> 1;
							
							setClip(0,0,s_w,s_h);
							setColor(0x000040);
							fillRect(x - 12, menuTop + h1 - 20, menuWidth + 24, vMenuName.size() * 16 - 3);
			
							setColor(0x204070);
							drawLine(x - 12, menuTop + h1 - 20, x + menuWidth + 11, menuTop + h1 - 20);
			
			                for (i = 0; i < vMenuName.size(); i++)
			                {
			                	str = ((String)vMenuName.elementAt(i)).trim();
			                	w2 = getStringWidth(str);
								drawString(str,(s_w - w2) >> 1,menuTop + h1 - 17 + i * 16);
							}
						}

							y1 = menuTop + h1 + (vMenuName.size() - 1) * 16;
							for (i = 0, n = 0; i < vMenu.size(); i++)
							{
								v = (Vector)vMenu.elementAt(i);

								for (k = 0; k < v.size(); k++, n++)
								{
									if ((n >= menuDisp) && (n - menuDisp < menuRange))
									{
										str = (String)(v.elementAt(k));
										if (i + 1 < vMenu.size() && isState)
										{
											str += "^:";
											str += (((Boolean)vState.elementAt(i)).booleanValue()) ? str_yes : str_no;
										}

										x1 = ((s_w - w1) >> 1);
										if (isPointer)
										{
											y2 = (v.size() - k) * menuHeight - 3;
											setClip(0,0,s_w,s_h);
											setColor(i == menuIndex ? 0x2000B0 : 0x001060);
											fillRect(x1 - 8, y1 - 3, w1 + 16, y2);
		
											if (i == menuIndex && (k == 0))
											{
												setColor(0x7090D0);
												drawLine(x1 - 8, y1 - 3, x1 + w1 + 7, y1 - 3);
											}

											if (i != menuIndex)
											{
												setColor(0x301090);
												drawLine(x1 - 8, y1 + y2 - 3, x1 + w1 + 7, y1 + y2 - 3);
											}
										}
										drawString(str,x1,y1 + (i == menuIndex ? 0 : 1));
										y1 += menuHeight;
									} // for k
								} // if
//								n += v.size();
							} // for i

					}
				}

				// needs to draw scoreboard
				if (!paused && isBoard)
				{
					x = s_w - fBoard.fw;
					if (s_h > 80) fBoard.draw(x,0);
					if ((state == STATE_SKATER_RUN_FINISH) || 
						((state == STATE_BIATHLON_RUN) && (man.state == STATE_BIATHLON_RUN_FINISH))) 
						timeToString(time_finish);
					else timeToString(time_current);
					drawChars(0,8,x + 8,1,1);
				}

				if ((go_delay > 0) && (fGo[go_index] != null))
				{
					fGo[go_index].draw((s_w - fGo[go_index].fw) >> 1,(s_h - fGo[go_index].fh) >> 1);
				}
				isScreen = 0;
			} // initOK
			else  
			{	// initOK == false
				// drawing status message while loading etc
				if (message != null && (isScreen == 1))
				{
					drawBgm();
					drawMessage(message);
					if (needLoadingIndicator)
					{
						setClip(0, 0, s_w, s_h);
						for (j = 0; j < snow.length; j++)
						{
							x = (snow[j] >> 24) & 0xFF;
							y = (snow[j] >> 16) & 0xFF;
							drawImage(snowflake_index, x, y);
						}
						updateSnow();
					}
				}

				// drawing progress bar
				if (isScreen == 2)
				{
					drawBgm();
					w2 = getStringWidth(message);
					x = (s_w - w2) >> 1;
					y = (s_h >> 1) - 8;
					drawString(message,x,y);
					setClip(0,0,s_w,s_h);
					setColor(0x00CCFF);
					fillRect(10,y + 12, (s_w - 20) * pb_cur / pb_max,4);
					setColor(0x2266EE);
					drawRect(10,y + 12, s_w - 20,4);

				}
			}
		}
		catch (Exception ex)
		{
//			ex.printStackTrace();
		}
		isPainting = false;
    }

    static boolean needLoadingIndicator = false;

    void drawMessage(String message)
    {
		v = prepareText(message,s_w - 8);
		k = v.size();
		y = (s_h - k * 16) >> 1;
		for (j = 0; j < k; j++, y += 16)
		{
			str = ((String)v.elementAt(j)).trim();
			drawString(str,(s_w - getStringWidth(str)) >> 1,y);
		}
    }

    void updateSnow()
    {
    	for (j = 0; j < snow.length; j++)
    	{
			x = (snow[j] >> 24) & 0xFF;
			y = (snow[j] >> 16) & 0xFF;
			k = (snow[j] >> 8)  & 0xFF;
			h = snow[j] & 0xFF;

			y += 4;
			x += 1 - k - k;
			if (y > h)
			{
				h = y + 10 + rnd(20) * 2;
				k = 1 - k;
			}

			if (y > s_h)
			{
				x = rnd(s_w);
				y = 0;
				k = rnd(1);
				h = rnd(20) * 2 + 10;
			}
		   	snow[j] =  (x & 0xFF) << 24;
		   	snow[j] |= (y & 0xFF) << 16;
    		snow[j] |= (k & 0xFF) << 8;
		   	snow[j] |= h & 0xFF;
		}
    }

    void drawGhostName(int x,int y, int color)
    {
		if (m_ghost != null)
		{
			setClip(0,0,s_w,s_h);
			setColor(0x202020);
			drawString(m_ghost,x,y,Graphics.BOTTOM | Graphics.HCENTER);
			setColor(color);
			drawString(m_ghost,x,y + 1,Graphics.BOTTOM | Graphics.HCENTER);
		}
    }

    int pb_cur = 0, pb_max = 0;
    void drawLogo(boolean needRast)
    {
		setColor(needRast ? 0x000000 : 0xEFF5FB);
		fillRect(0,0,s_w,s_h);
		if ((img[logo0_index] != null) && (img[logo1_index] != null))
		{
			x1 = getImageWidth(logo0_index);
			x2 = getImageWidth(logo1_index);
			h2 = getImageHeight(logo1_index);
			y1 = 0;
//#if Size_0
			y2 = 1;
			logoTop = h2 + y2 + 4;
//#endif

//#if Motorola && C650
			y1 = h2 - 20;
			y2 = 0;
			logoTop = h2 + 8;
//#elif Size_1
			y1 = h2 - 8;
			y2 = 0;
			logoTop = h2 + 8;
//#endif

			boolean needLogo = true;

//#if Size_2
			y2 = 5;
			logoTop = h2 + y2 + 6;
//#endif
			if (!needRast)
			{
//#if Size_1
				drawImage(logo1_index,(s_w - x2) >> 1,bgTop + y2);
				drawImage(logo0_index,(s_w - x1) >> 1,bgTop + y1);
//#else
				drawImage(logo0_index,(s_w - x1) >> 1,bgTop + y1);
				drawImage(logo1_index,(s_w - x2) >> 1,bgTop + y2);
//#endif
			}
			else
//#if Size_0
			if (menuLevel == 0)
//#endif
			if (needLogo) drawImage(logo1_index,(s_w - x2) >> 1,bgTop + y2);
		}
    }

    void drawRast()
    {
    	if (gd != null)
    	{
    		setClip(0,0,s_w,s_h);
	    	if (img[rast_index] != null)
    		for (i = 0; i < s_w; i += 16)
		    	for (j = 0; j < s_h; j += 16)
		    		drawImage(rast_index,i,j);
		}
    }

    void drawBgm()
    {
		setClip(0,0,s_w,s_h);
		setColor(0x000000);
		fillRect(0,0,s_w,s_h);
	}

	public void run()
	{
        t = Thread.currentThread();
       	if (mainThread != null); // dummy code 
		while (t == mainThread)
		{
			try{ t.sleep(3); } catch(Exception iex){}
			tcur = System.currentTimeMillis() - tstart;
			runFlag = true;

			if (running)
			{
				needRepaint = false;
				for (task_i = 0; task_i < tasks.length; task_i++)
				while (runFlag && tasks[task_i] < tcur)
//				if (tcur > 65)
				{
//					tstart = System.currentTimeMillis();
        			tasks[task_i] += taskTimes[task_i];
					if (task_i == 0)
					{
						try
						{
	    					switch(state)
    						{
							case STATE_SKIJUMP_RUN_SCORES:
								if (--state_delay <= 0)
								{
									storeTime(G_SKIJUMP,total_points,total_points);
								}
								break;
    						case STATE_SKIJUMP_RUN:
    							update_skijump();
    							break;
    						case STATE_BIATHLON_RUN:
    							if (go_delay > 0) go_delay--;
    							if (go_index >= 2) update_biathlon(); // GO message shown
    							else
	    						{
    								if (go_delay <= 0)
    								{
    									go_delay = 20;
    									if (++go_index >= 2)
    									{
	    									ghost_time = ghost_time_w = 0;
    										man.period = total_points = 0;
											time_finish = 0;
    										time_start = System.currentTimeMillis(); 
    									}
    									else
    									{
    									}
		    						}
	    						}
    							break;
							case STATE_BIATHLON_RUN_SCORES:
								if (--state_delay <= 0)
								{
									m_v1 = (int)(time_total / 10);
									m_v2 = man.missed;
									storeTime(G_BIATHLON,total_points,m_v1);
								}
								break;
							case STATE_SKATER_RUN:
	    						if (go_delay > 0) go_delay--;
    						
   								if (go_index >= 2) update_skater_run(); // GO message shown
    							else
    							{
    								if (go_delay <= 0)
	    							{
    									go_delay = 20;
    									if (++go_index >= 2)
    									{
    										ghost_time = ghost_time_w = 0;
    										man.period = total_points = 0;
											time_finish = 0;
											frames_passed = 0;
    										time_start = System.currentTimeMillis(); 
	    								}
	    								else 
	    								{
	    								}
	    							}
    							}
    			       	
								break;
							case STATE_SKATER_RUN_FINISH:
								update_skater_run();
								if (--state_delay <= 0)
								{
									go_delay = 0;
									state = STATE_SKATER_RUN_SCORES;
									state_delay = 40;
								}
								break;
							case STATE_SKATER_RUN_SCORES:
								update_skater_run();
								if (--state_delay <= 0)
								{
									m_v1 = (int)(time_total / 10);
									m_v2 = 0;
									storeTime(G_SKATER,total_points,m_v1);
								}
								break;
	   						case STATE_MENU:
    							updateMenu();
    							break;
	    					case STATE_EDITOR_FINISH:
	    						if (--state_delay <= 0) editOk(new String(editText));
	    						break;
	    					case STATE_EDITOR:
    							updateEditor();
    							break;
    						case STATE_INTRO:
    							if (--state_delay <= 0 || (isKeyPressed))
	    						{
                                    img[logo0_index] = null;
                                    loadLogo();
    								loadImages(true);
    								state = STATE_LOGO;
    								state_delay = 40;
    							}
    							break;
							case STATE_PLACE:
								if (--state_delay <= 0 || (isKeyPressed))
								{
									menuLevel = 9;
									returnMenu();
									action = key_action = NO_ACTION;
    								runFlag = false;
								}
								break;
	    					case STATE_LOGO:
    							if (--state_delay <= 0 || (logoTop != -1 && isKeyPressed))
    							{
    								action = key_action = NO_ACTION;
		   			           		menuLevel = 0;
		   			           		returnMenu();
    								runFlag = false;
    							}
	    					}
            	    	}
            		    catch (Exception e)
						{
//		   	           		e.printStackTrace();
	                	}
						if (!isKeyPressed) action = key_action = NO_ACTION;
						needRepaint = true;
					}
	        	}
    	    	if (needRepaint)
				{
					doRepaint();
				}
        	}
		}
	}

	void doRepaint()
	{
//#if Siemens && (!SX1)
		paint(getGraphics());
		flushGraphics();
//#else
    	repaint();
 		serviceRepaints();
//#endif
	}

    synchronized public void start() 
    {
        if (mainThread == null) 
        {
            mainThread = new Thread(this);
            mainThread.start();
        }
    }
    
    synchronized public void stop() 
    {
        mainThread = null;
        try
        {
        	rs.closeRecordStore();
        }
        catch(Exception ex){}
    }
    ////////////////////////////////////////////////////////
    
	// header fields
	static byte cipherAddition = 0;
	static byte cipherValue = 0;
	//

	// file table fields
	static byte[] filename = null;
	static int pk_size[];
	static int pk_index[];

	static String sFileName = null;

	byte[] buffer = null;
	//
	// internal function which reads one coded byte and decodes it
	byte readCByte() throws IOException
	{
		int r = in.read();
		r = (cipherAddition == 1 ? ((r - cipherValue) & (0xFF)) : ((r + cipherValue) & 0xFF));
		return (byte)r;
	}

	private int readCInt() throws IOException
	{
		int r = (byte)readCByte() & 0x00FF;
		r |= ((byte)readCByte() & 0x00FF) << 8;
		r |= ((byte)readCByte() & 0x00FF) << 16;
		r |= ((byte)readCByte() & 0x00FF) << 24;
		return r;
	}

	private int readCBytes(byte[]b, int l) throws IOException
	{
		boolean noZero = true;
		int i, n = 0;
		for (i = 0; i < l; i++)
		{
			b[i] = readCByte();
			if (b[i] != 0)
			{
				if (noZero) n++;
			}
			else noZero = false;
		}
		return n;
	}

	int _readInt() throws Exception
	{
		int r = (byte)in.read() & 0x000000FF;
		r |= ((byte)in.read() & 0x000000FF) << 8;
		r |= ((byte)in.read() & 0x000000FF) << 16;
		r |= ((byte)in.read() & 0x000000FF) << 24;
		return r;
	}

	void loadFromStream(int loadMode) throws Exception
	{
		int i, i2, j, k;
		pk_size = new int[img.length];
		pk_index = new int[img.length];
		filename = new byte[10];

		int dx = 0;

		in.read(filename,0,6);
		if (!(new String(filename,0,6).equals("DEEPAK"))) return;
		_readInt();
		int w2 = _readInt();

		cipherAddition = (byte)in.read();
		cipherValue = (byte)in.read();
		in.read(filename,0,10);
		_readInt();
		dx += 30;

		if (w2 > img.length) w2 = img.length;

		// search for entry name

		// reading file table
		int idx = 0;
		for (i = 0; i < w2 ; i++, dx += 22)
		{
			doRepaint();
			k = readCBytes(filename,filename.length);
			// searching max size of image
			pk_size[i] = readCInt();

			readCInt(); // dummy 4 bytes

			pk_index[i] = -1;
			readCInt();

			sFileName = new String(filename,0,k).toLowerCase();

			i2 = sFileName.indexOf(".");

			if (i2 != 1) sFileName = sFileName.substring(0,i2);

				for (j = 0; j < img_names.length; j++)
				{
					if (img_names[j] != null && (j != logo0_index) && (j != logo1_index)) 
					{
						if (img_names[j].equals(sFileName))
						{
							pk_index[i] = j;
							if (pk_size[i] > idx) idx = pk_size[i];
			   	
//							System.out.println("Enqueued " + img_names[j]);
							img_names[j] = null;
							break;
						}
					}
				}
		}
		sFileName = null;
		System.gc();

		if (idx > 0)
		{
			buffer = new byte[idx];
			// reading resources
			for (i = 0; i < w2; i++)
			{
				doRepaint();
				if (pk_index[i] != -1)
				{
					readCBytes(buffer,pk_size[i]);
					if (loadMode == 0)
					{
						img[pk_index[i]] = Image.createImage(buffer,0,pk_size[i]);
					}
				}
				else
				{
					in.skip(pk_size[i]);
				}
			}
			buffer = null;
		}

		in.close();
		in = null;

		pk_size = null;
		pk_index = null;
		filename = null;

		System.gc();
	}

	void loadResource(int index) 
	{
		try
		{
			if (img_names[index] != null)
			{
//#if GX10
				if (index == logo0_index) img[index] = img_cache[0];
				if (index == logo1_index) img[index] = img_cache[1];
				if (index == rast_index) img[index] = img_cache[2];
//#else
				createImage(index, "/Res/" + img_names[index] + ".png");
//#endif
				img_names[index] = null;
			}
		}
		catch(Exception ex)
		{
//			ex.printStackTrace();
		}

	}

	public boolean loadImages(boolean onlyLogo)
	{
		// reading the header	
		
		loadResource(logo0_index);
		loadResource(logo1_index);
		loadResource(rast_index);

		if (onlyLogo) return true;

		int n;
		for (n = 0; n < 4; n++)
		try
		{
			in = midlet.getClass().getResourceAsStream("/Res/" + n + ".pak");
			loadFromStream(0);
		}
		catch(Exception ex){}

		return true;
	}

	//////////////////////////////////////////////////////////////////////////////////////////
    static Vector parse(String str)
    {
    	str2 = "";
    	h = str.length() - 1;
    	v2 = new Vector();
    	for (int i = 0; i <= h; i++)
    	{
    		ch = str.charAt(i);
    		if (i == h) str2 += ch;
    		if ((ch == ',') || (i == h))
    		{
    			try
    			{
    				v2.addElement(new Integer(Integer.parseInt(str2)));
    			}
    			catch(Exception ex){}
    			str2 = "";
    		}
    		else str2 += ch;
    	}
    	str2 = null;
    	return v2;
    }
    ///////////////////////////////////////////////////////////////////////////////////
    static String gp(String name)
    {
    	if (hp == null)
    	{
    	    hp = new Hashtable();
            try
            {
	    	    in = midlet.getClass().getResourceAsStream("/Res/wg.c");
    			int i,mode = 0;
    			String key = "",value = "";
    			while((i = in.read()) != -1)
    			{
    				ch = (char)i;
    				if (ch == '\n')
    				{
    					mode = 0;
    					if ((key.length() > 0) && (value.length() > 0))
    					{
    						hp.put(key.trim().toLowerCase(),value.trim().toLowerCase());
						}
    					key = value = "";
    				}

    				if (mode == 2){}
    				else
    				if (ch == '#')
    				{
    					mode = 2;
    				}
    				else
    				if (ch == '=')
    				{
    					mode = 1;
    				}
    				else
    				{
    					if (mode == 0) key += ch;
    					if (mode == 1) value += ch;
    				}
    			}
    			in.close();
    		}
    		catch(Exception e){}
    		in = null;
    	}
		return (String)hp.get(name);
    }

	/////////////////////////////////////////////////////////////////////////////////////
    static void drawString(String str, int x, int y)
    {
    	sl = str.length();
    	if (sl > buf.length) sl = buf.length;
    	for (si = 0; si < sl; si++)
    		buf[si] = str.charAt(si);
    	drawChars(0,sl,x,y);
    }

    static boolean needCalcTabulations = true;
    static void calcSn(boolean drawing)
    {
		sn = 0;
		if ((sc >= '0') && (sc <= '9')) sn = (int)(sc - '0');
		if (abci == 1)
		{
			if (sc == ':') sn = 10;
		}
		if (abci == 2)
		{
			if (sc == 'a') sn = 10;
			if (sc == 'g') sn = 11;
			if (sc == 'k') sn = 12;
			if (sc == 'l') sn = 13;
			if (sc == 'm') sn = 14;
			if (sc == 'o') sn = 15;
		}
    	if (abci == 0)
    	{
			if (sc == '^')
			{
				if (drawing)
				{
					sx = tabw + tabx[tabi];
					tabw = sx;
				}
				else
				{   	
					sx += 4;
					if (needCalcTabulations)
					{
						tabw = sx - tabw;
						if (tabw > tabx[tabi]) 
						{
							tabx[tabi] = tabw;
						}
					}
				}
				tabi++;
			}

			if (sc == '#') sn = 36;
			if (sc == '.') sn = 37;
			if (sc == ':') sn = 38;
			if (sc == '_') sn = 39;
			if (sc == ',') sn = 40;
			if (sc == '*') sn = 41;
			if (sc == '@') sn = 42;
			if (sc == '(') sn = 43;
			if (sc == ')') sn = 44;

			if (sc >= 'a' && (sc <= 'z')) sn = (int)(sc - 'a') + 10;
			if (sc >= 'A' && (sc <= 'Z')) sn = (int)(sc - 'A') + 10;

			if (sc == '\'') sn = 45;
	
			if (sc == 0xC0) sn = 46;
			if (sc == 0xC1) sn = 47;
			if (sc == 0xC2) sn = 48;
			if (sc == 0xC4) sn = 49;
			if (sc == 0xC5) sn = 50; //a

			if (sc == 0xC6) sn = 51;

			if (sc == 0xC7) sn = 52;

			if (sc == 0xC8) sn = 53;
			if (sc == 0xC9) sn = 54;
			if (sc == 0xCA) sn = 55;
			if (sc == 0xCB) sn = 56; //e

			if (sc == 0xCC) sn = 57;
			if (sc == 0xCD) sn = 58;
			if (sc == 0xCE) sn = 59;
			if (sc == 0xCF) sn = 60; //i

			if (sc == 0xD1) sn = 61; //n

			if (sc == 0xD2) sn = 62;
			if (sc == 0xD3) sn = 63;
			if (sc == 0xD4) sn = 64;
			if (sc == 0xD6) sn = 65; //o

			if (sc == 0xD9) sn = 66;
			if (sc == 0xDA) sn = 67;
			if (sc == 0xDB) sn = 68;
			if (sc == 0xDC) sn = 69; //u

			if (sc == '+') sn = 70;
			if (sc == '-') sn = 71;

			if (sc == '?') sn = 72;
			if (sc == 0x20AC) sn = 73; // euro

		}
    }

	static void drawChars(int start,int cnt,int x,int y)
	{
		drawChars(start,cnt,x,y,0);
	}

	static void drawChars(int start,int cnt,int x,int y,int index)
	{
		abci = index;
		try
		{
    		sx = 0;
    		tabi = tabw = 0;
    		for (si = 0; si < cnt; si++)
    		{
    			sc = buf[si + start];
    			calcSn(true);
    			if (sc != '^')
    			{
	    			if (sc != ' ')
    				{
	    				setClip(sx + x,y,abcw[abci][sn],abch[abci]);
		    			drawImage(abc_index[abci],sx + x - abcx[abci][sn],y - abcy[abci][sn]);
			    	}
					sx += abcw[abci][sn];
					if (abcw[abci][sn] > 9) sx--;
					if (abci > 0) sx ++;
				}
	    	}
    	}
    	catch(Exception ex){}
    }
    
    static int getStringWidth(String str)
    {
    	sx = 0;
    	sl = str.length();
    	tabi = tabw = 0;
    	for (si = 0; si < sl; si++)
    	{
			sc = str.charAt(si);
			calcSn(false);
   			if (sc != '^')
   			{
				sx += abcw[abci][sn];
				if (abcw[abci][sn] > 9) sx--;
				if (abci > 0) sx ++;
			}
    	}
    	return sx;
    }
    //////////////////////////////////////////////////////////////////////////////////
    static int t_s,t_secs,t_mins,t_ms;
    static void timeToString(long millis)
    {
    	t_ms = ((int)(millis / 10)) % 100;
    	t_s = (int)(millis / 1000);

    	t_secs = t_s % 60;
    	t_mins = t_s / 60;
    	intToString(t_mins,0,2);
    	buf[2] = ':';
    	intToString(t_secs,3,2);
    	buf[5] = ':';
    	intToString(t_ms,6,2);
    }

	static int its_x,its_i,its_n;
    static void intToString(int n,int disp,int digits)
    {
    	for (its_x = n, its_i = digits - 1; its_i >= 0; its_i --, its_x /= 10)
    		buf[disp + its_i] = (char)(its_x % 10 + '0');
    }

    boolean getState(int index)
    {
    	return ((Boolean)vState.elementAt(index)).booleanValue();
    }

    static void addItem(String item,boolean state)
    {
    	addItem(item);
    	vState.addElement(new Boolean(state));
    }

    static void addItem(String item)
    {
    	if (vMenu == null) vMenu = new Vector();
    	v = prepareText(item.charAt(0) == ' ' ? item.substring(1) : item, s_w - 8);
    	menuSize += v.size();
    	vMenu.addElement(v);
    }

    static void addListItem(String item)
    {
    	if (vMenu == null) vMenu = new Vector();
    	v = new Vector();
    	v.addElement(item);
   		w2 = getStringWidth(item);
   		if (w2 > menuItemWidth) menuItemWidth = w2;
    	menuSize++;
    	vMenu.addElement(v);
    }

    static Vector prepareText(String text, int wmax)
    {
    	v = new Vector();
    	w1 = text.length();
    	StringBuffer sb1 = new StringBuffer();
    	StringBuffer sb2 = new StringBuffer();
    	sx = j = 0;
    	for (i = 0; i < w1; i++)
    	{
    		sc = text.charAt(i);
    		calcSn(false);
   			sb2.append(sc);
			sx += abcw[abci][sn];

   			if (sx >= wmax)
    		{
    			if (sb1.length() > 0)
    			{
					v.addElement(sb1.toString());
					sb1.setLength(0);
				}
				else
				{
					v.addElement(sb2.toString());
					sb2.setLength(0);
				}
				sx -= j;
			}

			if ((sc == ' ') || (sc == ',') || (sc == '.') || (sc == '@'))
    		{   	
				sb1.append(sb2.toString());
				sb2.setLength(0);
				j = sx;
    		}
    	}
    	if (sb1.length() + sb2.length() > 0)
    	{
    		sb1.append(sb2.toString());
    		v.addElement(sb1.toString());
    	}
    	x1 = getStringWidth(str_yes);
    	x2 = getStringWidth(str_no);
    	if (x2 > x1) x1 = x2;

    	for (i = 0; i < v.size(); i++)
    	{
    		str2 = (String)v.elementAt(i);
    		if (isState)str2 += "^";

    		w2 = getStringWidth(str2);

    		if (isState) w2 += x1;
    		if (w2 > menuItemWidth) menuItemWidth = w2;
    	}
    	w1 = 0;
    	return v;
    }

    void addText(String text)
    {
    	v = prepareText(text,s_w - 16);
    	for (i = 0; i < v.size(); i++)
    	{
    		v2 = new Vector();
    		v2.addElement((String)v.elementAt(i));
    		vMenu.addElement(v2);
    		v2 = null;
    	}
    	v = null;
    }

	void showMessage(String message)
	{
		WinterSports.main.setScreen(message);
		try{ Thread.sleep(2500); } catch(Exception ex2){}
	}

/*******************************************************************************************************************
 *******************************************************************************************************************
 ********************                                                                        ***********************
 ********************                           Menu Functions                               ***********************
 ********************                                                                        ***********************
 *******************************************************************************************************************
 *******************************************************************************************************************/
 	static int m_state = -1;
    static RecordStore rs = null;

	static int C_ADD_RECORD		= 0x0000FFFF;

    static int C_UID			= 1;		// record type for UID

	static final int G_BIATHLON	= 7;
	static final int G_SKATER	= 8;
	static final int G_SKIJUMP	= 9;

    static int C_INTERNET 		= 2;		// record type for internet setup
    static int C_SOUND	 		= 3;		// record type for internet setup
    static int C_UNAME			= 4;		// record type for player name

    static String uname = ".....";			// player name
    static boolean isNameSaved;


	static String version 	= "";

    static int menuLevel = 0;			// which menu is active

    static boolean m_paused = false;
    static String m_ghost = null;
    static int m_v1,m_v2;
    static long m_time_left = 0;

    static String player = "player";
    static int hsid,game_id,game_time,game_time_local,found;
    static String game_name = "Game";

	static String an[] = null;
	static int as[] = null;

    static int r_v1,r_v2;
	static String r_player = null;
    static RecordEnumeration re = null;

    void endGame()
    {
    	running = initOK = false;
    	setScreen(text[25]);
    	release();
   		menuLevel = 2;
   		m_paused = false;
   		returnMenu();
    }

    void returnMenu()
    {
    	if (m_paused) menuLevel = 10;
		m_paused = false;
       	running = false;
		menuLast = -1;
        switch (menuLevel)
        {
	        case 0:
                initMenu(text[0],true,false,true); // winter sports
				addItem(text[1]);		// game
				addItem(text[58]);		// help
				addItem(text[3]);		// about
				addItem(text[4]);		// quit
				break;
	        case 1:
				menuLast = 0;
                initMenu(text[5],true,false,false); // select game
				addItem(text[6]); // ski jump
				addItem(text[7]); // biathlon
				addItem(text[8]); // skater
				addItem(text[9]); // back
				break;
			case 2:
				menuLast = 1;
                initMenu(game_name,true,false,false);
				addItem(text[10]); // play
				addItem(text[11]); // load ghost
				addItem(text[50]); // hiscores
				addItem(text[2]); // help
				addItem(text[9]); // back
				break;			
			case 4:
				menuLast = 2;
                initMenu(text[12],true,false,false); // upload ghost
				addItem(text[13]); // yes
				addItem(text[14]); // no
				break;
			case 5:
				menuLast = 2;
                initMenu(text[15],true,false,false); // cant save
				addItem(text[16]); // retry
				addItem(text[17]); // cancel
				break;
			case 9:
				menuLast = 2;
                initMenu(text[18],true,false,false); // play again
				addItem(text[13]); // yes
				addItem(text[14]);  // no
				break;
            case 10:
            	menuLast = 10;
				initMenu(text[19],true,false,false); // pause menu
				addItem(text[20]); // resume
				addItem(text[21]); // restart
				addItem(text[22]); // exit race
				addItem(text[4]); // quit
				break;
		}
		initTasks();
    }

    public static final int MENU_NEW 			= 0;
    public static final int MENU_HELP			= 3;
    public static final int MENU_ABOUT			= 4;
    public static final int MENU_QUIT			= 5;

    void menuOk(int n)
    {
    	switch (menuLevel)
    	{                                                                                    
    		case 0:

    			i = MENU_NEW;

				switch (n)
				{
					case 1: i = MENU_HELP; 		break;
					case 2: i = MENU_ABOUT; 	break;
					case 3: i = MENU_QUIT; 		
                }


        		switch(i)
        		{	
        			case MENU_NEW:
            	 		// single game
	             		menuLevel = 1;
    	         		returnMenu();
        	     		break;

					case MENU_HELP:
						running = false;
            			menuLevel = 7;
						menuLast = 0;
						initMenu(text[2],false,false,false); // help
						addText(text[42]);
						initTasks();
						break;

					case MENU_ABOUT:
						running = false;
            			menuLevel = 7;
						menuLast = 0;
						initMenu(text[3],false,false,false); // about
						addText(text[0] + " V." + version + " " + text[46]);
						initTasks();
						break;
					case MENU_QUIT:
	                	midlet.exit();
                }
                break;
    		case 1:
    			if (n == 0 && (game_id != G_SKIJUMP))
    			{
   					game_id = G_SKIJUMP;
    				game_name = text[6]; // ski jump
    			}
    			if (n == 1 && (game_id != G_BIATHLON))
   				{
   					game_id = G_BIATHLON;
    				game_name = text[7]; // biathlon
   				}

    			if (n == 2 && (game_id != G_SKATER))
    			{
    				game_id = G_SKATER;
	    			game_name = text[8]; // skater
    			}

    			menuLevel = 2;
    			if (n == 3) // back
    				menuLevel = 0;
    			returnMenu();
    			break;	 
    		case 2:      
    			if (n == 0)
    			{
					init(game_id, false, null, 0);
					initTasks();
   	           	}
   	           	else
                if (n == 1) // load ghost
    			{
			        // load ghost from RMS
			       	init(game_id,true,null,0);
			       	initTasks();
    			}
   	           	else
   	           	if (n == 2) // hiscores
   	           	{
					running = false;
					menuLevel = 6;
					menuLast = 2;
					initMenu(text[50],false,false,false);
					bestScores(game_id);
					initTasks();
   	           	}
   	           	else
   	           	if (n + 2 == vMenu.size())
   	           	{
            		menuLevel = 6;
					menuLast = 2;
					running = false;
					initMenu(text[2],false,false,false); // help
					if (game_id == G_BIATHLON) addText(text[43]);
					if (game_id == G_SKATER) addText(text[44]);
					if (game_id == G_SKIJUMP) addText(text[45]);
					initTasks();
   	           	}
   	           	else
   	           	{
   	           		menuLevel = 1;
   	           		returnMenu();
   	           	}
	           	break;
    		case 3: 
   				running = false;
    			if (n + 1 >= vMenu.size())
    			{
					menuLevel = 2;
    				returnMenu();
    			}
    			else
    			{
    				m_ghost = (String)(((Vector)vMenu.elementAt(n)).elementAt(0));
    				i = m_ghost.indexOf("^");
	    			if (i != -1) m_ghost = m_ghost.substring(i + 1);
    				i = m_ghost.indexOf("^");
    				if (i != -1) m_ghost = m_ghost.substring(0,i);
    				init(game_id, true, (String)vMenuId.elementAt(n), 3);
	    			initTasks();
    			}
   				break;
   			case 4:
   				save(n == 0);
   				break;
   			case 5:
				running = false;			
   				menuLevel = 2;
   				if (n == 0) uploadScore();
   				else
   				{
   					// call PLAY AGAIN menu
   					menuLevel = 9;
   					returnMenu();
   				}
   				break;
   			case 6:  // back from help
   				menuLevel = 2;
   				returnMenu();
   				break;
   			case 7: // back from about
   				menuLevel = 0;
   				returnMenu();
   				break;
   			case 9: // play again menu
   				if (n == 0)
   				{
   					m_restart();
   				}
   				else
   				{
   					endGame();
   				}
   				break;
   			case 10: // pause menu
   				m_paused = true;
   				if (n == 0)
   				{
   					// continue
   					paused = m_paused = false;
   					state = m_state;
   					time_start += System.currentTimeMillis() - m_time_left;
					initTasks();
				}
				else
				if (n == 1)
				{
   					// restart
   					m_paused = paused = false;
   					m_restart();
   				}
   				else
   				if (n == 2)
   				{
   					// exit level
   					endGame();
   				}
   				else
   				{
   					// quit
                	midlet.exit();
   				}
   				break;
	        default:
	        	menuLevel = 0;
	        	returnMenu();
	        	break;
    	}
    }


    void m_restart()
    {
    	running = false;
    	initOK = false;
		if (game_id == G_BIATHLON) state = STATE_BIATHLON_RUN;
		if (game_id == G_SKATER)   state = STATE_SKATER_RUN;
		if (game_id == G_SKIJUMP)  state = STATE_SKIJUMP_RUN;
		restart();
		initTasks();
    }

    void menuBack(int n)
    {
    	if (menuLast != 10)
    	{
    		m_paused = paused = false;
			menuLevel = n;
			returnMenu();
    	}
    	else
    	{
    		menuLevel = 10;
    		menuOk(0);
    	}
    }

    void editOk(String param)
    {
		// player name entered
		player = uname = param;
		putVar(C_UNAME,1,player);
		isNameSaved = true;
		if (found == 0 || (hsid != C_ADD_RECORD)) putRecord(hsid,game_id,game_time_local);
		uploadScore();
    }

    void editBack()
    {
    	resourcesLoaded = false;
		menuLevel = 2;
    	returnMenu();
    }

    void storeTime(int game_id,int time,int time_local)
    {
    	this.game_id = game_id;
    	this.game_time = time;
    	this.game_time_local = time_local;

		save(false);
	}

	void save(boolean needSave)
	{
    	found = 0;
    	int id,max = game_time_local;
    	// write local ghost
    	writeGhostLocal(game_id,game_time_local,ghost_data_w,ghost_data_count_w);

    	// search for a place in hiscores
    	hsid = C_ADD_RECORD;
   		startRead("*");
   	    while ((id = readNext()) != -1) 
		{
   			if (r_v1 == game_id)
			{
   		    	found = 1;
   		    	if ((r_v2 < max && (game_id == G_SKIJUMP)) || 
   		    		(r_v2 > max && (game_id != G_SKIJUMP)))
   	    		{
   		    		hsid = id;
   		    		max = r_v2;
   		    	}
	    	}
      	}

  	    if (((found == 0 || (hsid != C_ADD_RECORD))) || needSave) 
		{
			// enter player name
    		running = false;
    		initEditor("NAME",uname,5);
    		initTasks();
		}
		else
		{
			menuLevel = 9;
			returnMenu();
		}
	}

	void uploadScore()
	{
		running = false;			
		menuLevel = 9;
		returnMenu();
	}

	void bestScores(int game_id)
	{
		String ssc;
		int i,j;

		as = new int[9];
		an = new String[9];
  		startRead("*");

		for (i = 0; (readNext() != -1) && (i < 9);) 
		{
   		    if (r_v1 == game_id)
			{
				as[i] = r_v2;
				an[i] = r_player;

				i++;
   		    }
		}

		if (i == 0)
		{
			menuLevel = 2;
			returnMenu();
		}
		else
		{
			sort(0,as.length - 1);

			for (i = as.length - 1, j = 1; i >= 0; i--, j++)
			{
				str = an[i];
				if (game_id == G_SKIJUMP)
				{
					intToString(as[i],0,4);
					ssc = new String(buf,0,4);
				}
				else
				{
					timeToString(as[i] * 10);
					ssc = new String(buf,0,8);
				}
				addListItem(j + ".^" + str + "^" + ssc);
			}
		}
		str = null;
		ssc = null;
		as = null;
		an = null;
	}

	int part(int l, int r)
	{
		int i,j;
		int v,b;
		v = as[r];
		i = l - 1;
		j = r;
		do
		{
			if (game_id == G_SKIJUMP)
			{
				do
				{
					j--;
				}
				while ((as[j] > v) && (j != (i + 1)));

				do
				{
					i++;
				}
				while ((as[i] < v) && (i != (j - 1)));
			}
			else
			{
				do
				{
					j--;
				}
				while ((as[j] < v) && (j != (i + 1)));

				do
				{
					i++;
				}
				while ((as[i] > v) && (i != (j - 1)));
			}

			b = as[i];
			as[i] = as[j];
			as[j] = b;

			str = an[i];
			an[i] = an[j];
			an[j] = str;
		}
		while (i < j);
		as[j] = as[i];
		as[i] = as[r];
		as[r] = b;

		an[j] = an[i];
		an[i] = an[r];
		an[r] = str;

		return i;
	}

	// QuickSort procedure: arr - any array, l - lower index, t - upper index
	void sort(int l,int t)
	{
		int i;
		if (l < t) 
		{
			i = part(l,t);
			sort(l,i - 1);
			sort(i + 1,t);
		}
	}

	static String filter = null;
	// part of interface
    public boolean matches(byte[] candidate) throws IllegalArgumentException
    {
		return true;
    }

	public int compare(byte[] rec1, byte[] rec2)
    {
    	return RecordComparator.EQUIVALENT;
    }

    int getVar(int type)
    {
    	startRead("*");		
   	    while(readNext() != -1) 
   	    {
	   	    if (r_v1 == type)
   		    {
   	    		return r_v2;
	   	    }
	   	}
    	return 0;
    }

    void putVar(int type,int value,String s)
    {
    	int foundId = -1,id;
    	startRead("*");		
   	    while((id = readNext()) != -1) if (r_v1 == type) foundId = id;
    	String oldPlayer = player;
    	player = s;
		putRecord(foundId,type,value);
		player = oldPlayer;
    }

    void startRead(String f)
    {
    	try 
    	{
	    	filter = f;
			re = rs.enumerateRecords((RecordFilter)this, (RecordComparator)this, true);
    	}
    	catch (Exception ex) 
    	{
    	}
    }

    int readNext()
    {
    	try 
    	{
	    	if (re.hasNextElement())
    		{
    			int id = re.nextRecordId();
	    		DataInputStream in = new DataInputStream(new ByteArrayInputStream(rs.getRecord(id)));
			    r_v1 = in.readInt();
			    r_v2 = in.readInt();
			    r_player = in.readUTF();

			    in.close();
	    		return id;
	    	}
    	}
    	catch (Exception ex) 
    	{
    	}
    	return -1;
    }

    void putRecord(int remove_id,int v1,int v2)
    {
    	try
    	{
    		ByteArrayOutputStream baos = new ByteArrayOutputStream();
    		DataOutputStream out = new DataOutputStream(baos);
    		out.writeInt(v1);
    		out.writeInt(v2);
    		out.writeUTF(player);
    		byte[] b = baos.toByteArray();

			if ((remove_id != C_ADD_RECORD) && (remove_id != -1)) 
				rs.setRecord(remove_id, b, 0, b.length);
			else 
				rs.addRecord(b, 0, b.length);
    	}
    	catch(Exception ex)
    	{
//    		ex.printStackTrace();
    	}
    }
    int readGhostLocal(int game_id,byte[] data)
    {
    	try
    	{
			RecordStore rsg = RecordStore.openRecordStore("wsg" + game_id,true);
			try
			{
				if (rsg.getNumRecords() > 0) return rsg.getRecord(1,data,0);
			}
			catch(Exception ex2)
			{
			}
			rsg.closeRecordStore();
		}
		catch(Exception ex)
		{
		}
		return 0;
    }

    void writeGhostLocal(int game_id,int new_points,byte[] data,int count)
    {
    	try
    	{
			RecordStore rst = RecordStore.openRecordStore("wst" + game_id,true);
			RecordStore rsg = RecordStore.openRecordStore("wsg" + game_id,true);

	    	int points = (game_id == G_SKIJUMP ? 0 : 0x7FFFFFFF);
	    	byte[] dataBuffer = null;
    		if (rst.getNumRecords() > 0)
    		{
    			dataBuffer = rst.getRecord(1);
    		}

    		if (dataBuffer == null) dataBuffer = new byte[4];
	    	else points = (dataBuffer[0] & 0x000000FF) | 
						((dataBuffer[1] << 8)  & 0x0000FF00) | 
    					((dataBuffer[2] << 16) & 0x00FF0000) | 
    					((dataBuffer[3] << 24) & 0xFF000000);

    		if ((points > new_points && (game_id != G_SKIJUMP)) || 
    			(points < new_points && (game_id == G_SKIJUMP)))
    		{                                  	
    			dataBuffer[0] = (byte)(new_points & 0x000000FF);
	    		dataBuffer[1] = (byte)((new_points >> 8) & 0x000000FF);
    			dataBuffer[2] = (byte)((new_points >> 16) & 0x000000FF);
    			dataBuffer[3] = (byte)((new_points >> 24) & 0x000000FF);

    			if (points == 0x7FFFFFFF || (points == 0))
    			{
    				rst.addRecord(dataBuffer,0,4);
    				rsg.addRecord(data,0,count);
    		   	}
    			else
    			{
    				rst.setRecord(1,dataBuffer,0,4);
		    		rsg.setRecord(1,data,0,count);
    			}
    		}
    		rst.closeRecordStore();
    		rsg.closeRecordStore();
    		dataBuffer = null;
    	}
    	catch(Exception ex)
    	{
    	}
    }

}              

